fix(android): stop the resource shrinker from deleting Dart-named drawables
Root cause found, and it is not the stale build cache I claimed earlier.
flutter clean was good hygiene and changed nothing here, because nothing
was cached: the resources were being deliberately removed.
Flutter's own Gradle plugin enables shrinking on every release build --
FlutterPlugin.kt, `releaseBuildType.isMinifyEnabled = true` and
`isShrinkResources = true` -- no matter what app/build.gradle.kts says. The
shrinker keeps what it can see referenced, and it cannot see
`MediaControl.custom(androidIcon: 'drawable/ic_auto_eq_on')`: that is a
string inside Dart, resolved at runtime through getIdentifier. So both
equalizer icons were stripped from every release APK ever built.
The evidence that pins it, from the APK pulled off the device:
ic_stat_pluriwave present <- referenced as R.drawable from Kotlin,
4 call sites in the alarm notifications
ic_auto_eq_on absent <- named only in a Dart string
ic_auto_eq_off absent <- named only in a Dart string
Same folder, same file shape, same commit range. The only difference is
whether a real R.drawable reference exists, which is exactly what the
shrinker looks for.
The consequence was never a blank button. getResourceId returns 0 for an
unresolvable name, PlaybackStateCompat.CustomAction.Builder throws on a 0
icon, and that throw aborts AudioService.setState before the media session
is activated -- so Android Auto held a frozen, inactive session. Dead
playback screen, play that never became pause, the app losing its pane to
any app with a live session, audio playing "as if it were not the app".
One shrunk file, four symptoms, since 31 July (2540556).
Two protections, because they fail differently:
- res/raw/keep.xml with tools:keep is the official mechanism for
dynamically resolved resources and is what actually binds the shrinker;
- RecursosResueltosPorNombre.kt gives them genuine R.drawable references,
the same thing that kept ic_stat_pluriwave alive all along.
station_art_* are kept too. They are reached the same way, through
android.resource:// URIs built in Dart, and survived only by luck.
Tests: 1165, unchanged -- this is a build-configuration fix, and no Dart
test can see it. The CI resource guard is what verifies it now.
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Protects the drawables that only Dart names from the resource shrinker.
|
||||
|
||||
Flutter's own Gradle plugin turns shrinking on for every release build
|
||||
(FlutterPlugin.kt: `releaseBuildType.isMinifyEnabled = true` and
|
||||
`isShrinkResources = true`), regardless of what app/build.gradle.kts says.
|
||||
The shrinker keeps what it can see referenced — and it cannot see
|
||||
`MediaControl.custom(androidIcon: 'drawable/ic_auto_eq_on')`, because that
|
||||
is a string inside Dart, resolved at runtime via
|
||||
`getResources().getIdentifier(...)`. So it removed both equalizer icons
|
||||
from every release APK.
|
||||
|
||||
The consequence was not a blank button. `getResourceId` returns 0 for a
|
||||
name it cannot resolve, `PlaybackStateCompat.CustomAction.Builder` throws
|
||||
on a 0 icon, and that throw aborts `AudioService.setState` before the media
|
||||
session is activated — leaving Android Auto with a frozen, inactive
|
||||
session. Dead playback screen, play that never became pause, the app losing
|
||||
its pane to any app with a live session, and audio playing "as if it were
|
||||
not the app". One shrunk file, four symptoms, from 31 July (commit 2540556).
|
||||
|
||||
Proven, not assumed: the installed APK was pulled off the device and its
|
||||
resource table read. `ic_stat_pluriwave` was present, both equalizer icons
|
||||
were not — and `ic_stat_pluriwave` is the only one of the three that Kotlin
|
||||
references as a real `R.drawable`, from the alarm notifications. A genuine
|
||||
reference survives shrinking; a name living in a Dart string does not.
|
||||
|
||||
ANY new drawable that Dart resolves by name must be listed here, and in the
|
||||
resource guard in .gitea/workflows/build.yml, which reads the built APK's
|
||||
resource table and fails the build if one of them went missing.
|
||||
-->
|
||||
<resources xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:keep="@drawable/ic_auto_eq_on,@drawable/ic_auto_eq_off,@drawable/ic_stat_pluriwave,@drawable/station_art_*" />
|
||||
Reference in New Issue
Block a user