Ridurre le dimensioni dell'app

Gli utenti spesso evitano di scaricare app che sembrano troppo grandi, in particolare nei mercati emergenti in cui i dispositivi si connettono a reti 2G e 3G non funzionanti o si basano su piani dati. In questa pagina viene descritto come ridurre le dimensioni di download dell'app, che consente a più utenti di scaricarla.

Caricare l'app con Android App Bundle

Carica la tua app come Android App Bundle per salvare immediatamente le dimensioni dell'app quando la pubblichi su Google Play. Android App Bundle è un formato di caricamento che include tutte le risorse e il codice compilato dell'app, ma impedisce la generazione degli APK e l'accesso a Google Play.

Il modello di pubblicazione di app di Google Play utilizza quindi l'app bundle per generare e pubblicare APK ottimizzati per la configurazione del dispositivo di ogni utente, in modo che gli utenti scarichino solo il codice e le risorse necessarie per eseguire l'app. Non devi creare, firmare e gestire più APK per supportare dispositivi diversi e gli utenti ricevono download più piccoli e ottimizzati.

Poiché Google Play impone una limitazione delle dimensioni di download compresse di massimo 200 MB per le app pubblicate con gli app bundle, ti consigliamo comunque di applicare le linee guida descritte in questa pagina per ridurre il più possibile le dimensioni di download dell'app.

Informazioni sulla struttura dell'APK

Prima di ridurre le dimensioni dell'app, è utile comprendere la struttura dell'APK di un'app. Un file APK è costituito da un archivio ZIP che contiene tutti i file che costituiscono la tua app. Questi file includono file di classe Java, file di risorse e un file contenente risorse compilate.

Un APK contiene le seguenti directory:

  • META-INF/: contiene i file di firma CERT.SF e CERT.RSA, nonché il file manifest MANIFEST.MF.
  • assets/: contiene gli asset dell'app, che l'app può recuperare utilizzando un oggetto AssetManager.
  • res/: contiene risorse non compilate in resources.arsc.
  • lib/: contiene il codice compilato specifico per il livello software di un processore. Questa directory contiene una sottodirectory per ogni tipo di piattaforma, ad esempio armeabi, armeabi-v7a, arm64-v8a, x86, x86_64 e mips.

Un APK contiene anche i seguenti file. È obbligatorio solo AndroidManifest.xml:

  • resources.arsc: contiene risorse compilate. Questo file contiene i contenuti XML di tutte le configurazioni della cartella res/values/. Lo strumento di pacchettizzazione estrae questi contenuti XML, li compila in formato binario e li archivia. Questi contenuti includono stringhe e stili di lingua, nonché percorsi a contenuti non inclusi direttamente nel file resources.arsc, come file di layout e immagini.
  • classes.dex: contiene le classi compilate nel formato file DEX compreso dalla macchina virtuale Dalvik o ART.
  • AndroidManifest.xml: contiene il file manifest di Android di base. Questo file elenca il nome, la versione, i diritti di accesso e i file della libreria di riferimento dell'app. Il file utilizza il formato XML binario di Android.

Riduci il numero e le dimensioni delle risorse

Le dimensioni dell'APK hanno un impatto sulla velocità di caricamento dell'app, sulla quantità di memoria che utilizza e sulla quantità di energia consumata. Puoi ridurre l'APK riducendo il numero e le dimensioni delle risorse che contiene. In particolare, puoi rimuovere le risorse che la tua app non utilizza più e utilizzare oggetti Drawable scalabili al posto dei file immagine. In questa sezione vengono descritti questi metodi e altri metodi per ridurre le risorse nella tua app al fine di ridurre le dimensioni complessive dell'APK.

Rimuovi le risorse inutilizzate

Lo strumento lint, uno strumento di analisi del codice statico incluso in Android Studio, rileva le risorse nella cartella res/ a cui il codice non fa riferimento. Quando lo strumento lint rileva una risorsa potenzialmente inutilizzata nel tuo progetto, visualizza un messaggio come quello nell'esempio seguente:

res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
    to be unused [UnusedResources]

Le librerie che aggiungi al codice potrebbero includere risorse inutilizzate. Gradle può rimuovere automaticamente le risorse per tuo conto se attivi shrinkResources nel file build.gradle.kts della tua app.

Kotlin

android {
    // Other settings.

    buildTypes {
        getByName("release") {
            minifyEnabled = true
            shrinkResources = true
            proguardFiles(getDefaultProguardFile('proguard-android.txt'), "proguard-rules.pro")
        }
    }
}

trendy

android {
    // Other settings.

    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

Per utilizzare shrinkResources, attiva la riduzione del codice. Durante il processo di compilazione, R8 rimuove prima il codice inutilizzato. Successivamente, il plug-in Android Gradle rimuove le risorse inutilizzate.

Per ulteriori informazioni sulla riduzione del codice e delle risorse e su altri modi in cui Android Studio riduce le dimensioni dell'APK, consulta la pagina Ridurre, offuscare e ottimizzare l'app.

Nel plug-in Android Gradle 7.0 e versioni successive, puoi dichiarare le configurazioni supportate dalla tua app. Gradle passa queste informazioni al sistema di build utilizzando la versione resourceConfigurations e l'opzione defaultConfig. Il sistema di compilazione impedisce quindi la visualizzazione nell'APK delle risorse di altre configurazioni non supportate, riducendone le dimensioni. Per ulteriori informazioni su questa funzionalità, consulta Rimuovere le risorse alternative inutilizzate.

Riduci al minimo l'utilizzo delle risorse dalle librerie

Quando sviluppi un'app per Android, in genere utilizzi librerie esterne per migliorarne l'usabilità e la versatilità. Ad esempio, puoi fare riferimento ad AndroidX per migliorare l'esperienza utente sui dispositivi precedenti oppure puoi utilizzare Google Play Services per recuperare le traduzioni automatiche dei testi all'interno della tua app.

Se una libreria è progettata per un server o un computer, può includere molti oggetti e metodi non necessari per l'app. Per includere solo le parti della libreria necessarie alla tua app, puoi modificare i file della raccolta se la licenza ti consente di modificare la raccolta. Puoi anche usare una raccolta alternativa ottimizzata per il mobile per aggiungere funzionalità specifiche alla tua app.

Decodifica di immagini animate native

In Android 12 (livello API 31), l'API NDK ImageDecoder viene estesa per decodificare tutti i dati relativi a frame e tempistiche dalle immagini che utilizzano GIF animate e formati file WebP animati.

Usa ImageDecoder invece di librerie di terze parti per ridurre ulteriormente le dimensioni degli APK e trarre vantaggio da futuri aggiornamenti relativi alla sicurezza e alle prestazioni.

Per maggiori dettagli sull'API ImageDecoder, consulta la pagina API reference e l'esempio su GitHub.

Supporta solo densità specifiche

Android supporta diverse densità dello schermo, ad esempio:

  • ldpi
  • mdpi
  • tvdpi
  • hdpi
  • xhdpi
  • xxhdpi
  • xxxhdpi

Anche se Android supporta le densità precedenti, non è necessario esportare gli asset rasterizzati in ogni densità.

Se sai che solo una piccola percentuale di utenti dispone di dispositivi con densità specifiche, valuta se devi raggruppare tali densità nella tua app. Se non includi le risorse per una specifica densità dello schermo, Android scala automaticamente le risorse esistenti progettate per altre densità dello schermo.

Se la tua app ha bisogno solo di immagini scalate, puoi risparmiare ancora più spazio impostando una singola variante di un'immagine in drawable-nodpi/. Ti consigliamo di includere almeno una variante dell'immagine xxhdpi nella tua app.

Per ulteriori informazioni sulle densità dello schermo, consulta Dimensioni e densità dello schermo.

Utilizza oggetti disegnabili

Alcune immagini non richiedono una risorsa immagine statica. Il framework può disegnare dinamicamente l'immagine in fase di runtime. Gli oggetti Drawable, o <shape> in XML, possono occupare una piccola quantità di spazio nell'APK. Inoltre, gli oggetti Drawable XML producono immagini monocromatiche conformi alle linee guida di Material Design.

Riutilizza le risorse

Puoi includere una risorsa separata per le varianti di un'immagine, ad esempio le versioni colorate, ombreggiate o ruotate della stessa immagine. Tuttavia, ti consigliamo di riutilizzare lo stesso insieme di risorse e di personalizzarle in base alle tue esigenze in fase di runtime.

Android fornisce diverse utilità per cambiare il colore di un asset, usando gli attributi android:tint e tintMode.

Puoi anche omettere le risorse che sono solo un equivalente ruotato di un'altra risorsa. Il seguente snippet di codice fornisce un esempio di come "Non mi piace" in "Non mi piace" ruotando al centro dell'immagine e ruotandola di 180 gradi:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_thumb_up"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromDegrees="180" />

Rendering dal codice

Puoi anche ridurre le dimensioni dell'APK eseguendo il rendering procedurale delle immagini. Il rendering procedurale libera spazio perché non memorizzi più un file immagine nell'APK.

Analizza i file PNG

Lo strumento aapt può ottimizzare le risorse immagine inserite in res/drawable/ con compressione senza perdita di dati durante il processo di compilazione. Ad esempio, lo strumento aapt può convertire un PNG a colori reali che non richiede più di 256 colori in un PNG a 8 bit con una tavolozza dei colori. In questo modo si ottiene un'immagine di pari qualità, ma con un ingombro di memoria inferiore.

aapt presenta le seguenti limitazioni:

  • Lo strumento aapt non riduce i file PNG contenuti nella cartella asset/.
  • I file immagine devono utilizzare al massimo 256 colori affinché lo strumento aapt possa ottimizzarli.
  • Lo strumento aapt potrebbe aumentare il numero dei file PNG già compressi. Per evitare che ciò accada, puoi utilizzare il flag isCrunchPngs per disabilitare questa procedura per i file PNG:
  • Kotlin

        buildTypes.all { isCrunchPngs = false }
        

    trendy

        buildTypes.all { isCrunchPngs = false }
        

Comprimi file PNG e JPEG

Puoi ridurre le dimensioni dei file PNG senza perdere la qualità dell'immagine con strumenti come pngcrush, pngquant o zopflipng. Tutti questi strumenti possono ridurre le dimensioni del file PNG mantenendo la qualità percepita dell'immagine.

Lo strumento pngcrush è particolarmente efficace. Questo strumento esegue l'iterazione dei filtri PNG e dei parametri zlib (Deflate), utilizzando ogni combinazione di filtri e parametri per comprimere l'immagine. Sceglie quindi la configurazione che restituisce l'output compresso più ridotto.

Per comprimere i file JPEG, puoi utilizzare strumenti come packJPG e guetzli.

Usa il formato file WebP

Anziché utilizzare i file PNG o JPEG, puoi utilizzare anche il formato file WebP per le immagini. Il formato WebP offre compressione e trasparenza con perdita di dati, come JPG e PNG, e può fornire una compressione migliore rispetto a JPEG o PNG.

Con Android Studio puoi convertire immagini BMP, JPG, PNG o GIF statiche in formato WebP. Per saperne di più, consulta Creare immagini WebP.

Utilizza grafica vettoriale

Puoi utilizzare grafiche vettoriali per creare icone indipendenti dalla risoluzione e altri contenuti multimediali scalabili. Puoi usare queste immagini per ridurre notevolmente l'impatto ambientale dell'APK. Le immagini vettoriali sono rappresentate in Android come VectorDrawable oggetti. Con un oggetto VectorDrawable, un file di 100 byte può generare un'immagine nitida delle dimensioni dello schermo.

Tuttavia, il sistema impiega molto più tempo per eseguire il rendering di ogni oggetto VectorDrawable e le immagini più grandi richiedono ancora più tempo per essere visualizzate sullo schermo. Pertanto, ti consigliamo di utilizzare queste grafiche vettoriali solo per la visualizzazione di immagini di piccole dimensioni.

Per ulteriori informazioni sull'utilizzo di oggetti VectorDrawable, consulta Disegni.

Utilizza grafica vettoriale per le immagini animate

Non utilizzare AnimationDrawable per creare animazioni fotogramma per fotogramma, perché questa operazione richiede l'inclusione di un file bitmap separato per ogni frame dell'animazione, il che aumenta drasticamente le dimensioni dell'APK.

Utilizza invece AnimatedVectorDrawableCompat per creare disegnabili di vettori animati.

Riduci il codice nativo e Java

Puoi usare i seguenti metodi per ridurre le dimensioni del codebase Java e nativo nella tua app.

Rimuovi il codice generato non necessario

Assicurati di comprendere l'impatto di qualsiasi codice generato automaticamente. Ad esempio, molti strumenti di buffer di protocollo generano un numero eccessivo di metodi e classi, il che può raddoppiare o triplicare le dimensioni della tua app.

Evita le enumerazioni

Una singola enum può aggiungere da 1,0 a 1,4 kB al file classes.dex della tua app. Queste aggiunte possono accumularsi rapidamente per sistemi complessi o librerie condivise. Se possibile, valuta la possibilità di utilizzare l'annotazione @IntDef e la riduzione del codice per eliminare le enumerazioni e convertirle in numeri interi. Questa conversione del tipo conserva tutti i vantaggi di sicurezza dei tipi delle enum.

Riduci le dimensioni dei file binari nativi

Se la tua app utilizza il codice nativo e l'NDK di Android, puoi anche ridurre le dimensioni della versione release dell'app ottimizzando il codice. Due tecniche utili sono la rimozione dei simboli di debug e la mancata estrazione delle librerie native.

Rimuovere i simboli di debug

L'utilizzo dei simboli di debug ha senso se l'app è in fase di sviluppo e deve ancora essere sottoposta a debug. Usa lo strumento arm-eabi-strip fornito nell'NDK di Android per rimuovere i simboli di debug non necessari dalle librerie native. In seguito, puoi compilare la build della release.

Evita di estrarre le librerie native

Quando crei la versione di release dell'app, pacchettizza i file .so non compressi nell'APK impostando useLegacyPackaging su false nel file build.gradle.kts dell'app. Se disabiliti questo flag, PackageManager non potrà copiare i file .so dall'APK nel file system durante l'installazione. Questo metodo riduce gli aggiornamenti dell'app.

Mantenere più APK sottili

L'APK potrebbe includere contenuti che gli utenti scaricano ma non utilizzano mai, ad esempio risorse di lingua o per densità dello schermo aggiuntive. Per garantire un download minimo per gli utenti, carica l'app su Google Play utilizzando Android App Bundle. Il caricamento di app bundle consente a Google Play di generare e pubblicare APK ottimizzati per la configurazione del dispositivo di ogni utente, in modo che possa scaricare solo il codice e le risorse necessarie per eseguire la tua app. Non devi creare, firmare e gestire più APK per supportare dispositivi diversi e gli utenti ricevono download più piccoli e ottimizzati.

Se non pubblichi l'app su Google Play, puoi segmentarla in più APK, differenziati per fattori quali dimensioni dello schermo o supporto della texture GPU.

Quando un utente scarica la tua app, il dispositivo riceve l'APK corretto in base alle funzionalità e alle impostazioni del dispositivo. In questo modo, i dispositivi non ricevono asset per funzionalità che non hanno. Ad esempio, se un utente ha un dispositivo hdpi, non ha bisogno di risorse xxxhdpi che potresti includere per i dispositivi con display a densità più elevata.

Per ulteriori informazioni, consulta Creazione di più APK e Supporto di più APK.