Personalizza le risorse da conservare

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:

Dipendenze → Principale → Gusto build → Tipo di build

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.