Ridurre le dimensioni dell'app

Spesso gli utenti evitano di scaricare app che sembrano troppo grandi, in particolare nei mercati emergenti in cui i dispositivi si connettono a reti 2G e 3G instabili o funzionano con piani con limiti di dati. In questa pagina viene descritto come ridurre le dimensioni del download dell'app, in modo da consentire a un maggior numero di utenti di scaricarla.

Caricare l'app con Android App Bundle

Carica la tua app come Android App Bundle per ridurre immediatamente le dimensioni dell'app quando la pubblichi su Google Play. Android App Bundle è un formato di caricamento che include tutto il codice e le risorse compilati della tua app, ma rimanda la generazione e la firma dell'APK a Google Play.

Il modello di pubblicazione delle app di Google Play utilizza quindi il tuo app bundle per generare e pubblicare APK ottimizzati per la configurazione del dispositivo di ogni utente, in modo che scarichi solo il codice e le risorse di cui ha bisogno per eseguire la tua app. Non devi creare, firmare e gestire più APK per supportare dispositivi diversi e gli utenti ottengono download più piccoli e ottimizzati.

Google Play applica una limitazione di dimensione del download compresso di 200 MB per le app pubblicate con app bundle. È possibile utilizzare dimensioni maggiori con Play Feature Delivery e Play Asset Delivery, ma l'aumento delle dimensioni dell'app può influire negativamente sul successo delle installazioni e aumentare le disinstallazioni, pertanto ti consigliamo di applicare le linee guida descritte in questa pagina per ridurre al massimo le dimensioni del 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 contenente tutti i file che compongono l'app. Questi file includono file di classi 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 che non vengono 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. Solo AndroidManifest.xml è obbligatorio:

  • resources.arsc: contiene risorse compilate. Questo file contiene i contenuti XML di tutte le configurazioni della cartella res/values/. Lo strumento di packaging estrae questi contenuti XML, li compila in formato binario e li archivia. Questi contenuti includono stringhe e stili di lingua, nonché percorsi di 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 a cui fa riferimento l'app. Il file utilizza il formato XML binario di Android.

Riduci il numero e le dimensioni delle risorse

Le dimensioni dell'APK influiscono sulla velocità di caricamento dell'app, sulla quantità di memoria utilizzata e sul consumo di energia. Puoi ridurre le dimensioni dell'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 puoi utilizzare oggetti Drawable scalabili al posto dei file immagine. Questa sezione illustra questi metodi e altri modi per ridurre le risorse nella tua app al fine di diminuire le dimensioni complessive dell'APK.

Rimuovi le risorse inutilizzate

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

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

Le librerie aggiunte al codice potrebbero includere risorse inutilizzate. Gradle può rimuovere automaticamente le risorse per tuo conto se attivi shrinkResources nel file build.gradle.kts dell'app.

Kotlin

android {
    // Other settings.

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

Groovy

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 per Gradle rimuove le risorse non utilizzate.

Per ulteriori informazioni sull'ottimizzazione del codice e delle risorse e su altri modi in cui Android Studio riduce le dimensioni dell'APK, consulta Ottimizzare, offuscare e ridurre le dimensioni dell'app.

In Android Gradle Plugin 7.0 e versioni successive, puoi dichiarare le configurazioni supportate dalla tua app. Gradle le passa al sistema di compilazione utilizzando il flavor resourceConfigurations e l'opzione defaultConfig. Il sistema di compilazione impedisce quindi che le risorse di altre configurazioni non supportate vengano visualizzate nell'APK, riducendone le dimensioni. Per ulteriori informazioni su questa funzionalità, consulta la sezione Rimuovere le risorse alternative non utilizzate.

Riduci al minimo l'utilizzo delle risorse dalle librerie

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

Se una libreria è progettata per un server o un computer, può includere molti oggetti e metodi di cui la tua app non ha bisogno. Per includere solo le parti della libreria necessarie per la tua app, puoi modificare i file della libreria se la licenza ti consente di modificarla. Puoi anche utilizzare 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 NDKImageDecoder viene espansa per decodificare tutti i frame e i dati relativi ai tempi delle immagini che utilizzano i formati file GIF animati e WebP animati.

Utilizza ImageDecoder anziché librerie di terze parti per diminuire ulteriormente le dimensioni dell'APK e usufruire di aggiornamenti futuri relativi a sicurezza e prestazioni.

Per maggiori dettagli sull'API ImageDecoder, consulta API reference e il sample su GitHub.

Supporta solo densità specifiche

Android supporta diverse densità dello schermo, ad esempio:

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

Sebbene Android supporti le densità precedenti, non è necessario esportare gli asset rasterizzati in ogni densità.

Se sai che solo una piccola percentuale di utenti ha dispositivi con densità specifiche, valuta se devi includere queste densità nella tua app. Se non includi risorse per una densità dello schermo specifica, Android ridimensiona automaticamente le risorse esistenti progettate originariamente per altre densità dello schermo.

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

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

Utilizzare oggetti drawable

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

Riutilizzare le risorse

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

Android fornisce diverse utilità per modificare il colore di una risorsa utilizzando gli attributi android:tint e tintMode.

Puoi anche omettere le risorse che sono solo l'equivalente ruotato di un'altra risorsa. Il seguente snippet di codice fornisce un esempio di trasformazione di un "pollice su" in un "pollice giù" ruotando l'immagine di 180 gradi attorno al centro:

<?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" />

Generazione di un rendering dal codice

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

Comprimi 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 file PNG a colori reali che non richiede più di 256 colori in un file PNG a 8 bit con una tavolozza di colori. In questo modo si ottiene un'immagine di qualità uguale, ma con un'impronta in memoria inferiore.

aapt presenta le seguenti limitazioni:

  • Lo strumento aapt non riduce le dimensioni dei file PNG contenuti nella cartella asset/.
  • Affinché lo strumento aapt possa ottimizzarli, i file immagine devono utilizzare al massimo 256 colori.
  • Lo strumento aapt potrebbe gonfiare i file PNG già compressi. Per evitarlo, puoi utilizzare il flag isCrunchPngs per disattivare questa procedura per i file PNG:
  • Kotlin

        buildTypes.all { isCrunchPngs = false }
        

    Groovy

        buildTypes.all { isCrunchPngs = false }
        

Comprimire i file PNG e JPEG

Puoi ridurre le dimensioni dei file PNG senza perdere la qualità delle immagini utilizzando strumenti come pngcrush, pngquant o zopflipng. Tutti questi strumenti possono ridurre le dimensioni dei file PNG mantenendo la qualità percettiva delle immagini.

Lo strumento pngcrush è particolarmente efficace. Questo strumento esegue l'iterazione sui filtri PNG e sui parametri zlib (Deflate), utilizzando ogni combinazione di filtri e parametri per comprimere l'immagine. Quindi sceglie la configurazione che genera l'output compresso più piccolo.

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

Utilizzare il formato file WebP

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

Puoi convertire immagini BMP, JPG, PNG o GIF statiche esistenti in formato WebP utilizzando Android Studio. Per ulteriori informazioni, vedi Creare immagini WebP.

Utilizza immagini vettoriali

Puoi utilizzare le immagini vettoriali per creare icone indipendenti dalla risoluzione e altri contenuti multimediali scalabili. Puoi utilizzare queste immagini per ridurre notevolmente l'impronta dell'APK. Le immagini vettoriali sono rappresentate in Android come oggetti VectorDrawable. 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 VectorDrawable oggetto e le immagini più grandi impiegano ancora più tempo per essere visualizzate sullo schermo. Pertanto, ti consigliamo di utilizzare queste immagini vettoriali solo per la visualizzazione di immagini di piccole dimensioni.

Per ulteriori informazioni sull'utilizzo degli oggetti VectorDrawable, consulta Drawables.

Utilizza la grafica vettoriale per le immagini animate

Non utilizzare AnimationDrawable per creare animazioni frame-by-frame, perché ciò richiede di includere un file bitmap distinto per ogni frame dell'animazione, il che aumenta drasticamente le dimensioni dell'APK.

Utilizza invece AnimatedVectorDrawableCompat per creare elementi drawable vettoriali animati.

Riduci il codice nativo e Java

Puoi utilizzare i seguenti metodi per ridurre le dimensioni della base di codice Java e nativa nella tua app.

Rimuovi il codice generato non necessario

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

Evita le enumerazioni

Un singolo enum può aggiungere circa 1,0-1,4 KB al file classes.dex dell'app. Queste aggiunte possono accumularsi rapidamente per sistemi complessi o librerie condivise. Se possibile, valuta la possibilità di utilizzare l'annotazione @IntDef e il ridimensionamento del codice per rimuovere le enumerazioni e convertirle in numeri interi. Questa conversione di tipo preserva tutti i vantaggi di sicurezza del tipo degli enum.

Riduci le dimensioni dei binari nativi

Se la tua app utilizza codice nativo e Android NDK, puoi anche ridurre le dimensioni della versione di 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 è utile se la tua app è in fase di sviluppo e richiede ancora il debug. Utilizza lo strumento arm-eabi-strip fornito in Android NDK per rimuovere i simboli di debug non necessari dalle librerie native. Dopodiché, puoi compilare la build di release.

Evitare di estrarre le librerie native

Quando crei la versione release della tua app, includi i file .so non compressi nell'APK impostando useLegacyPackaging su false nel file build.gradle.kts dell'app. La disattivazione di questo flag impedisce a PackageManager di copiare i file .so dall'APK al file system durante l'installazione. Questo metodo consente di ridurre le dimensioni degli aggiornamenti dell'app.

Gestire più APK snelli

L'APK potrebbe contenere contenuti che gli utenti scaricano, ma che non utilizzano mai, come risorse linguistiche aggiuntive o per la densità dello schermo. Per contribuire a garantire un download minimo per i tuoi utenti, carica la tua app su Google Play utilizzando Android App Bundle. Il caricamento degli app bundle consente a Google Play di generare e pubblicare APK ottimizzati per la configurazione del dispositivo di ogni utente, in modo che scarichi 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 ottengono download più piccoli e ottimizzati.

Se non pubblichi la tua app su Google Play, puoi segmentarla in più APK, differenziati in base a fattori quali le dimensioni dello schermo o il supporto delle texture GPU.

Quando un utente scarica la tua app, il suo dispositivo riceve l'APK corretto in base alle sue funzionalità e impostazioni. 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 delle risorse xxxhdpi che potresti includere per i dispositivi con display ad alta densità.

Per ulteriori informazioni, vedi Creare più APK e Supporto di più APK.