Quando attivi l'ottimizzazione delle app, il comportamento predefinito dell'ottimizzatore è diverso per le diverse versioni di R8.
- Con il DSL aggiornato disponibile a partire da AGP 9.3 e versioni successive, la riduzione delle risorse è attivata per impostazione predefinita quando l'ottimizzazione è abilitata. Tieni presente che il DSL legacy, che richiede l'attivazione distinta dell'ottimizzazione del codice e delle risorse, è ancora supportato.
Per le versioni precedenti ad AGP 9.3, l'impostazione
isShrinkResources = trueindica all'ottimizzatore di rimuovere le risorse inutilizzate, il che contribuisce a ridurre le dimensioni dell'app. La riduzione delle risorse funziona solo in combinazione con la riduzione del codice, quindi se stai ottimizzando le risorse, imposta ancheisMinifyEnabled = true.
AGP 9.3+ (Kotlin)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
AGP 9.3+ (Groovy)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
DSL legacy (Kotlin)
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
DSL precedente (Groovy)
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
...
}
}
Se vuoi conservare o eliminare risorse specifiche, crea un file XML keep nelle risorse del progetto, ad esempio res/raw/my.package.keep.xml. Il file di conservazione
contiene i seguenti componenti:
- Tag
<resources>: contiene tutti gli elementi delle risorse secondarie e gli attributi keep/discard. - Attributo
tools:keep: accetta un elenco separato da virgole di nomi di risorse che identificano le risorse da conservare - Attributo
tools:discard: accetta un elenco separato da virgole di nomi di risorse che identificano le risorse da eliminare
Utilizza l'asterisco come carattere jolly per fare riferimento a più risorse nella stessa cartella, ad esempio:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
Specificare le risorse da eliminare potrebbe sembrare superfluo quando potresti eliminarle, ma eliminare le risorse può essere utile quando si utilizzano varianti di build.
Scegliere come target varianti di build specifiche
Per rimuovere le risorse solo in alcune varianti di compilazione, inserisci tutte le risorse nella directory del progetto comune, quindi crea un file my.package.build.variant.keep.xml diverso per ogni variante di compilazione nella directory delle risorse della variante. Nel file keep, specifica manualmente le risorse da rimuovere quando una determinata risorsa sembra essere utilizzata nel codice (e quindi non rimossa dal riduttore), ma sai che in realtà non verrà utilizzata per la variante di compilazione specificata.
Rimuovere le risorse alternative inutilizzate
Lo strumento di ottimizzazione rimuove solo le risorse a cui non fa riferimento il codice dell'app, il che significa che non rimuove le risorse alternative per le diverse configurazioni del dispositivo.
Utilizza la proprietà resConfigs di Android Gradle nel file build.gradle del modulo della tua app per rimuovere i file di risorse alternativi che non sono necessari per la tua app.
Ad esempio, se utilizzi una libreria che include risorse linguistiche (come Google Play Services), la tua app include tutte le stringhe di lingua tradotte per i messaggi in queste librerie, indipendentemente dal fatto che il resto dell'app sia tradotto nelle stesse lingue o meno. Per conservare solo le lingue supportate ufficialmente dalla tua app, specifica queste lingue utilizzando la proprietà resConfigs.
Vengono rimosse tutte le risorse per le lingue non specificate.
I seguenti snippet mostrano come limitare le risorse linguistiche solo all'inglese e al francese:
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
o
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
Quando pubblichi un'app utilizzando il formato Android App Bundle (AAB), per impostazione predefinita vengono scaricate solo le lingue configurate sul dispositivo di un utente quando l'utente installa l'app. Allo stesso modo, nel download sono incluse solo le risorse corrispondenti alla densità dello schermo del dispositivo e le librerie native corrispondenti all'ABI del dispositivo. Per saperne di più, consulta Riattivare o disattivare i tipi di APK di configurazione.
Per le app legacy rilasciate con APK (create prima di agosto 2021), puoi personalizzare le risorse di densità dello schermo o ABI da includere nell'APK creando più APK destinati a diverse configurazioni di dispositivi.
Evitare conflitti durante l'unione delle risorse
Per impostazione predefinita, il plug-in Android per Gradle (AGP) unisce le risorse con lo stesso nome,
ad esempio le risorse drawable con lo stesso nome che si trovano in cartelle delle risorse diverse.
Questo comportamento non è controllato dalla proprietà shrinkResources e non può essere disattivato perché è necessario per evitare errori quando più risorse hanno il nome a cui fa riferimento il codice.
L'unione delle risorse si verifica solo quando due o più file condividono nome, tipo e qualificatore identici. AGP seleziona il file che identifica come la scelta migliore tra i duplicati (in base a un ordine di priorità descritto di seguito) e passa solo quella risorsa ad AAPT per la distribuzione nell'artefatto di build finale.
AGP cerca risorse duplicate nelle seguenti posizioni:
- Risorse principali, associate al set di risorse principale, generalmente situate in
src/main/res/ - Overlay delle varianti, dal tipo di compilazione e dalle versioni di build
- Dipendenze del progetto della libreria
AGP unisce le risorse duplicate nel seguente ordine di priorità a cascata:
Ad esempio, se una risorsa duplicata viene visualizzata sia nelle risorse principali sia in una variante di build, Gradle seleziona la risorsa nella variante di build.
Se risorse identiche vengono visualizzate nello stesso set di risorse, Gradle non può unirle
ed emette un errore di unione delle risorse. Ciò può accadere se definisci più set di origini nella proprietà sourceSet del file build.gradle del modulo, ad esempio se src/main/res/ e src/main/res2/ contengono risorse identiche.
Risolvere i problemi relativi alla riduzione delle risorse
Quando riduci le risorse, la finestra Build mostra un riepilogo delle risorse rimosse dall'app. (Fai clic su Attiva/disattiva visualizzazione sul lato sinistro della finestra per visualizzare l'output di testo dettagliato di Gradle.) Ad esempio:
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle crea anche un file di diagnostica denominato resources.txt in
<module-name>/build/outputs/mapping/release/ (la stessa cartella dei file di output di ProGuard). Il file include dettagli come quali risorse fanno riferimento ad altre risorse e quali risorse vengono utilizzate o rimosse.
Ad esempio, per scoprire perché @drawable/ic_plus_anim_016 è ancora presente nella tua app,
apri il file resources.txt e cerca il nome del file. Potresti notare che
viene fatto riferimento a un'altra risorsa:
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
Ora devi sapere perché @drawable/add_schedule_fab_icon_anim è raggiungibile;
se cerchi verso l'alto, troverai la risorsa elencata sotto l'intestazione
Le risorse raggiungibili dalla radice sono: in resources.txt.
Ciò significa che esiste un riferimento al codice add_schedule_fab_icon_anim, ovvero
il relativo ID R.drawable è stato trovato nel codice raggiungibile.
A meno che non utilizzi il controllo rigoroso, gli ID risorsa possono essere contrassegnati come raggiungibili se sono presenti costanti stringa che sembrano poter essere utilizzate per costruire i nomi delle risorse caricate dinamicamente. In questo caso, se cerchi il nome della risorsa nell'output della build, potresti trovare un messaggio come questo:
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because its format-string matches string pool constant ic_plus_anim_%1$d.
Se visualizzi una di queste stringhe e hai la certezza che non venga utilizzata per caricare dinamicamente la risorsa specificata, utilizza l'attributo tools:discard nel file keep per comunicare al sistema di compilazione di rimuovere la risorsa.