Quando attivi l'ottimizzazione dell'app, l'impostazione isShrinkResources = true
invita l'ottimizzatore a 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 anche isMinifyEnabled = true
, ad esempio:
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = 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 keep
contiene i seguenti componenti:
- Tag
<resources>
: contiene tutti gli elementi delle risorse secondarie e gli attributi mantieni/elimina. - 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 il carattere 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 l'eliminazione delle risorse può essere utile quando utilizzi le varianti di compilazione.
Scegli come target varianti di build specifiche
Per rimuovere le risorse solo in alcune varianti di build, inserisci tutte le risorse nella directory del progetto comune, quindi crea un file my.package.build.variant.keep.xml
diverso per ogni variante di build 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 viene rimossa dallo shrinker), ma sai che in realtà non verrà utilizzata per la variante di build specificata.
Rimuovi le risorse alternative inutilizzate
L'ottimizzatore rimuove solo le risorse a cui non fa riferimento il codice dell'app, il che significa che non rimuoverà le risorse alternative per diverse configurazioni del dispositivo.
Utilizza la proprietà resConfigs
di Gradle per Android nel file build.gradle
del modulo della tua app per rimuovere i file di risorse alternative non 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 o meno nelle stesse lingue. Per mantenere solo le lingue supportate ufficialmente dalla tua app, specificale utilizzando la proprietà resConfigs
.
Eventuali risorse per le lingue non specificate vengono rimosse.
Gli snippet riportati di seguito 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 dell'utente quando l'utente installa l'app. Analogamente, nel download sono incluse solo le risorse corrispondenti alla densità dello schermo del dispositivo e le librerie native corrispondenti all'ABI del dispositivo. Per maggiori informazioni, consulta la sezione 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 ABI o di densità dello schermo da includere nell'APK generando più APK destinati a configurazioni di dispositivi diverse.
Evitare conflitti durante l'unione delle risorse
Per impostazione predefinita, il plug-in Android Gradle (AGP) unisce le risorse con lo stesso nome, come gli elementi drawable con lo stesso nome che si trovano in cartelle di 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 avviene solo quando due o più file condividono un nome, un tipo e un qualificatore della risorsa identici. AGP seleziona il file che identifica come la 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'elemento finale della compilazione.
AGP cerca risorse duplicate nelle seguenti posizioni:
- Risorse principali associate all'insieme di origini principale, in genere situate in
src/main/res/
- Sovrapposizioni delle varianti, dal tipo di build 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 un flavor di build, Gradle seleziona la risorsa nel flavor di build.
Se nello stesso set di origine vengono visualizzate risorse identiche, Gradle non può unificarle
e genera un errore di unione delle risorse. Questo può accadere se definisci più set di origini nella proprietà sourceSet
del file build.gradle
del modulo, ad esempio se sia src/main/res/
sia src/main/res2/
contengono risorse identiche.
Risolvere i problemi relativi al ridimensionamento 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 le risorse che fanno riferimento ad altre risorse e quelle utilizzate o rimosse.
Ad esempio, per scoprire perché @drawable/ic_plus_anim_016
è ancora nella tua app,
apri il file resources.txt
e cerca il nome file. Potresti scoprire 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 esegui una ricerca verso l'alto, troverai la risorsa elencata sotto l'intestazione Le risorse raggiungibili principali sono: in resources.txt
.
Ciò significa che esiste un riferimento a add_schedule_fab_icon_anim
nel codice, ovvero il suo ID R.drawable
è stato trovato nel codice raggiungibile.
A meno che non utilizzi un controllo rigoroso, gli ID risorsa possono essere contrassegnati come raggiungibili se esistono costanti di stringa che sembrano poter essere utilizzate per creare i nomi delle risorse per le risorse caricate dinamicamente. In questo caso, se cerchi il nome della risorsa nell'output di compilazione, potresti trovare un messaggio simile al seguente:
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 vedi una di queste stringhe e hai la certezza che non viene utilizzata per caricare dinamicamente la risorsa in questione, utilizza l'attributo tools:discard
nel file keep per indicare al sistema di compilazione di rimuovere la risorsa.