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 lavorano a piani con limiti di dati. In questa pagina viene descritto come ridurre le dimensioni di download della tua app per 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 risparmiare immediatamente le dimensioni dell'app quando la pubblichi su Google Play. Android App Bundle è un formato di caricamento che include tutto il codice compilato e le risorse della tua app, ma rimanda la generazione degli APK e la firma su 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 ciascun utente, in modo che scarichino solo il codice e le risorse necessari 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.

Google Play applica una limitazione relativa alle dimensioni di download compresse di 200 MB per le app pubblicate con app bundle. Dimensioni maggiori sono possibili utilizzando Play Feature Delivery e Play Asset Delivery, ma aumentare le dimensioni della tua app può influire negativamente sul successo delle installazioni e aumentare le disinstallazioni, quindi ti consigliamo di applicare le linee guida descritte in questa pagina per ridurre il più possibile le dimensioni di download della tua app.

Informazioni sulla struttura degli APK

Prima di ridurre le dimensioni dell'app, è utile comprendere la struttura del suo APK. Un file APK è costituito da un archivio ZIP contenente tutti i file che compongono 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 che non sono 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 file indicati di seguito. 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 pacchettizzazione estrae questi contenuti XML, li compila in formato binario e archivia i contenuti. Questi contenuti includono stringhe e stili di linguaggio, nonché percorsi di contenuti che non sono inclusi direttamente nel file resources.arsc, ad esempio 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 Android principale. Questo file elenca il nome, la versione, i diritti di accesso e i file delle librerie 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 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 la dimensione 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. In questa sezione vengono descritti 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, uno strumento di analisi di 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 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")
        }
    }
}

Alla moda

android {
    // Other settings.

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

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

Per maggiori informazioni sulla riduzione di codice e risorse e su altri modi in cui Android Studio riduce le dimensioni dell'APK, leggi l'articolo 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 di risorse di altre configurazioni non supportate nell'APK, riducendo le dimensioni dell'APK. Per ulteriori informazioni su questa funzionalità, consulta Rimuovere le risorse alternative inutilizzate.

Riduci al minimo l'utilizzo di risorse delle librerie

Quando sviluppi un'app per Android, in genere utilizzi librerie esterne per migliorare l'usabilità e la versatilità dell'app. 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 del testo all'interno della tua app.

Se una libreria è progettata per un server o un computer, può includere molti oggetti e metodi non necessari all'app. Per includere solo le parti della raccolta necessarie all'app, puoi modificare i file della raccolta se la licenza ti consente di modificare la raccolta. Puoi anche usare una libreria 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 espansa per decodificare tutti i frame e i dati di temporizzazione dalle immagini che utilizzano i formati file GIF animate e WebP animati.

Usa ImageDecoder al posto delle librerie di terze parti per ridurre ulteriormente le dimensioni degli APK e usufruire dei 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

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 è necessario raggruppare queste densità nella tua app. Se non includi risorse per una specifica densità dello schermo, Android scala automaticamente le risorse esistenti progettate in origine per altre densità dello schermo.

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

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

Utilizza oggetti disegnabili

Alcune immagini non richiedono una risorsa di immagini statiche. Il framework può invece disegnare l'immagine in modo dinamico in fase di runtime. Drawable oggetti (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.

Riutilizza 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 set di risorse e di personalizzarlo in base alle esigenze durante il runtime.

Android fornisce diverse utilità per modificare il colore di un asset, 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 "Mi piace" in "Non mi piace" ruotando la parte centrale dell'immagine di 180°:

<?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.

File PNG Crunch

Lo strumento aapt può ottimizzare le risorse immagine inserite in res/drawable/ con compressione senza perdita di dati durante il processo di creazione. 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 l'immagine avrà la stessa qualità, ma l'utilizzo di memoria ridotta.

aapt presenta le seguenti limitazioni:

  • Lo strumento aapt non comprime 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 gonfiare i file PNG già compressi. Per evitare questo problema, puoi utilizzare il flag isCrunchPngs per disabilitare questa procedura per i file PNG:
  • Kotlin

        buildTypes.all { isCrunchPngs = false }
        

    Alla moda

        buildTypes.all { isCrunchPngs = false }
        

Comprimi file PNG e JPEG

Puoi ridurre le dimensioni dei file PNG senza comprometterne la qualità con strumenti come pngcrush, pngquant o zopflipng. Tutti questi strumenti possono ridurre le dimensioni del file PNG senza compromettere la qualità percettiva 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ù piccolo.

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

Utilizza il formato file WebP

Anziché utilizzare i file PNG o JPEG, puoi utilizzare anche il formato file WebP per le tue immagini. Il formato WebP offre compressione e trasparenza con perdita di dati, ad esempio JPG e PNG, e può fornire 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 maggiori informazioni, vedi Creare immagini WebP.

Utilizza grafica vettoriale

Puoi utilizzare le grafiche vettoriali per creare icone che non dipendono dalla risoluzione e altri elementi multimediali scalabili. Puoi usare queste immagini per ridurre notevolmente l'utilizzo degli APK. Le immagini vettoriali sono rappresentate in Android come oggetti VectorDrawable. Con un oggetto VectorDrawable, un file da 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 richiedono ancora più tempo per essere visualizzate sullo schermo. Pertanto, valuta la possibilità di utilizzare queste grafiche vettoriali solo in caso di immagini di piccole dimensioni.

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

Utilizzare grafiche vettoriali per le immagini animate

Non utilizzare AnimationDrawable per creare animazioni fotogramma per fotogramma, perché ciò richiede l'inclusione di un file bitmap separato per ogni frame dell'animazione, aumentando drasticamente le dimensioni dell'APK.

Usa invece AnimatedVectorDrawableCompat per creare disegnabili vettoriali animati.

Riduci il codice nativo e Java

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

Rimuovi il codice generato non necessario

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

Evita enumerazioni

Una singola 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 la riduzione del codice per eliminare le enumerazioni e convertirle in numeri interi. Questa conversione di tipo conserva tutti i vantaggi in termini di sicurezza dei tipi delle enum.

Riduci le dimensioni dei file 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 non l'estrazione delle librerie native.

Rimuovere i simboli di debug

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

Evita di estrarre le librerie native

Quando crei la versione di release dell'app, puoi pacchettizzare i file .so decompressi nell'APK impostando useLegacyPackaging su false nel file build.gradle.kts dell'app. La disattivazione di questo flag impedisce a PackageManager di copiare file .so dall'APK al file system durante l'installazione. Questo metodo riduce gli aggiornamenti dell'app.

Mantieni APK snelli

L'APK potrebbe includere contenuti che gli utenti scaricano ma che non utilizzano mai, ad esempio risorse linguistiche o di densità per schermo. Per garantire un download minimo per i tuoi 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 ciascun utente, in modo che possano scaricare solo il codice e le risorse necessarie per eseguire l'app. Non è necessario creare, firmare e gestire più APK per supportare diversi dispositivi e gli utenti ricevono download più piccoli e ottimizzati.

Se non pubblichi la tua app su Google Play, puoi segmentare l'app in diversi APK, diversi 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 funzionalità e alle impostazioni del dispositivo. In questo modo, i dispositivi non ricevono asset per funzionalità di cui non dispongono. 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 maggiori informazioni, vedi Creare APK multipli e Supporto di più APK.