Mengurangi ukuran aplikasi Anda

Pengguna sering kali menghindari mendownload aplikasi yang tampak terlalu besar, terutama di pasar negara berkembang tempat perangkat terhubung ke jaringan 2G dan 3G yang tidak stabil atau menggunakan paket dengan batas data. Halaman ini menjelaskan cara mengurangi ukuran download aplikasi, yang memungkinkan lebih banyak pengguna untuk mendownload aplikasi Anda.

Mengupload aplikasi dengan Android App Bundle

Upload aplikasi sebagai Android App Bundle untuk segera menyimpan ukuran aplikasi saat Anda memublikasikan ke Google Play. Android App Bundle adalah format upload yang menyertakan semua kode dan resource terkompilasi dari aplikasi Anda, tetapi menangguhkan pembuatan dan penandatanganan APK ke Google Play.

Model penayangan aplikasi Google Play kemudian menggunakan app bundle Anda untuk membuat dan menayangkan APK yang dioptimalkan untuk setiap konfigurasi perangkat pengguna, sehingga pengguna hanya mendownload kode dan resource yang dibutuhkan untuk menjalankan aplikasi. Anda tidak perlu membuat, menandatangani, dan mengelola banyak APK untuk mendukung perangkat yang berbeda, dan pengguna mendapatkan hasil download yang lebih kecil dan lebih dioptimalkan.

Google Play menerapkan batasan ukuran download yang dikompresi sebesar 200 MB untuk aplikasi yang dipublikasikan dengan app bundle. Ukuran yang lebih besar mungkin menggunakan Play Feature Delivery dan Play Asset Delivery, tetapi meningkatkan ukuran aplikasi dapat berdampak negatif pada keberhasilan penginstalan dan meningkatkan uninstal, jadi sebaiknya terapkan pedoman yang dijelaskan di halaman ini untuk mengurangi ukuran download aplikasi Anda semaksimal mungkin.

Memahami struktur APK

Sebelum mengurangi ukuran aplikasi, sebaiknya pahami struktur APK aplikasi terlebih dahulu. File APK terdiri dari arsip ZIP yang berisi semua file yang membentuk aplikasi Anda. File ini meliputi file class Java, file resource, dan file yang berisi kompilasi resource.

APK berisi direktori berikut:

  • META-INF/: berisi file tanda tangan CERT.SF dan CERT.RSA, serta file manifes MANIFEST.MF.
  • assets/: berisi aset aplikasi, yang dapat diambil aplikasi menggunakan objek AssetManager.
  • res/: berisi resource yang tidak dikompilasi ke resources.arsc.
  • lib/: berisi kompilasi kode yang dikhususkan untuk lapisan software prosesor. Direktori ini berisi subdirektori untuk setiap jenis platform, seperti armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, dan mips.

APK juga berisi beberapa file berikut. Hanya AndroidManifest.xml yang wajib:

  • resources.arsc: berisi kompilasi resource. File ini berisi konten XML dari semua konfigurasi folder res/values/. Alat pengemasan mengekstrak konten XML ini, mengompilasikannya ke bentuk biner, dan mengarsipkan konten. Konten ini mencakup string dan gaya bahasa, serta jalur ke konten yang tidak disertakan secara langsung di file resources.arsc, seperti gambar dan file tata letak.
  • classes.dex: berisi kompilasi class dalam format file DEX yang dipahami oleh mesin virtual Dalvik atau ART.
  • AndroidManifest.xml: berisi file manifes Android inti. Daftar file ini mencakup nama, versi, hak akses, dan file library referensi aplikasi. File ini menggunakan format XML biner Android.

Mengurangi jumlah dan ukuran resource

Ukuran APK Anda berpengaruh terhadap kecepatan pemuatan aplikasi, banyaknya penggunaan memori, dan banyaknya daya yang digunakan. Anda dapat memperkecil APK dengan mengurangi jumlah dan ukuran resource yang ada di dalamnya. Secara khusus, Anda dapat menghapus resource yang tidak digunakan lagi oleh aplikasi, dan dapat menggunakan objek Drawable skalabel sebagai pengganti file gambar. Bagian ini membahas metode ini dan cara lain untuk mengurangi resource di aplikasi untuk mengurangi keseluruhan ukuran APK.

Membuang referensi yang tidak digunakan

Alat lint, penganalisis kode statis yang disertakan di Android Studio, mendeteksi resource di folder res/ yang tidak direferensikan oleh kode Anda. Saat menemukan resource yang mungkin tidak digunakan di project Anda, alat lint akan menampilkan pesan seperti dalam contoh di bawah ini:

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

Library yang Anda tambahkan ke kode dapat menyertakan resource yang tidak digunakan. Gradle dapat otomatis menghapus resource untuk Anda jika Anda mengaktifkan shrinkResources pada file build.gradle.kts aplikasi Anda.

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'
        }
    }
}

Untuk menggunakan shrinkResources, aktifkan penyingkatan kode. Selama proses build, mula-mula R8 menghapus kode yang tidak digunakan. Selanjutnya, plugin Android Gradle akan menghapus resource yang tidak digunakan.

Untuk mengetahui informasi selengkapnya tentang penyingkatan kode dan resource, serta cara lain Android Studio mengurangi ukuran APK, lihat Menyingkat, meng-obfuscate, dan mengoptimalkan aplikasi.

Di Plugin Android Gradle 7.0 dan yang lebih baru, Anda dapat mendeklarasikan konfigurasi yang didukung aplikasi. Gradle meneruskan informasi ini ke sistem build menggunakan ragam resourceConfigurations dan opsi defaultConfig. Lalu, sistem build mencegah resource dari konfigurasi lain yang tidak didukung agar tidak muncul di APK, sehingga dapat mengurangi ukuran APK. Untuk informasi selengkapnya terkait fitur ini, lihat Menghapus resource alternatif yang tidak digunakan.

Meminimalkan penggunaan resource dari library

Saat mengembangkan aplikasi Android, Anda biasanya menggunakan library eksternal untuk meningkatkan kegunaan dan fleksibilitas aplikasi. Misalnya, Anda dapat mereferensikan AndroidX untuk meningkatkan pengalaman pengguna di perangkat versi lebih lama, atau Anda dapat menggunakan Layanan Google Play untuk mengambil terjemahan otomatis untuk teks dalam aplikasi Anda.

Jika library dirancang untuk server atau desktop, library dapat menyertakan banyak objek dan metode yang tidak diperlukan aplikasi Anda. Untuk menyertakan bagian library yang diperlukan aplikasi saja, Anda dapat mengedit file library jika lisensinya mengizinkan Anda mengubah library. Anda juga dapat menggunakan library alternatif yang mobile-friendly untuk menambahkan fungsi tertentu ke aplikasi Anda.

Dekode gambar animasi native

Di Android 12 (level API 31), API ImageDecoder NDK telah diperluas untuk mendekode semua data waktu dan frame dari gambar yang menggunakan format file WebP animasi dan GIF animasi.

Gunakan ImageDecoder, bukan library pihak ketiga, untuk mengurangi ukuran APK secara maksimal dan dapatkan manfaat dari update selanjutnya yang terkait dengan keamanan serta performa.

Untuk detail selengkapnya tentang API ImageDecoder, lihat API reference dan sampel di GitHub.

Hanya mendukung kepadatan tertentu

Android mendukung berbagai kepadatan layar, seperti berikut:

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

Meskipun Android mendukung kepadatan sebelumnya, Anda tidak perlu mengekspor aset raster ke setiap kepadatan.

Jika Anda mengetahui bahwa hanya sebagian kecil pengguna Anda yang memiliki perangkat dengan kepadatan tertentu, pertimbangkan apakah Anda perlu menggabungkan kepadatan tersebut ke dalam aplikasi Anda. Jika Anda tidak menyertakan resource untuk kepadatan layar tertentu, Android akan otomatis menskalakan resource yang ada, yang awalnya dirancang untuk kepadatan layar lainnya.

Jika aplikasi Anda hanya memerlukan gambar yang diskalakan saja, Anda dapat menghemat lebih banyak ruang dengan memiliki satu varian gambar dalam drawable-nodpi/. Sebaiknya sertakan setidaknya satu varian gambar xxhdpi di aplikasi Anda.

Untuk informasi selengkapnya terkait kepadatan layar, lihat Ukuran dan kepadatan layar.

Menggunakan objek yang dapat digambar

Beberapa gambar tidak memerlukan resource gambar statis. Sebagai gantinya, framework dapat membuat gambar secara dinamis saat runtime. Objek Drawable—atau <shape> dalam XML, tidak membutuhkan banyak ruang di APK. Selain itu, objek Drawable XML menghasilkan gambar monokrom yang sesuai dengan panduan Desain Material.

Menggunakan kembali referensi

Anda dapat menyertakan resource terpisah untuk variasi gambar, misalnya versi diwarnai, diberi bayangan, atau diputar dari gambar yang sama. Namun, sebaiknya Anda menggunakan kembali set resource yang sama dan menyesuaikannya sesuai kebutuhan saat runtime.

Android menyediakan beberapa utilitas untuk mengubah warna aset, baik menggunakan atribut android:tint maupun tintMode.

Anda juga dapat menghilangkan resource yang hanya merupakan ekuivalen yang diputar dari resource lainnya. Cuplikan kode berikut menyediakan contoh pengubahan ikon "suka" menjadi "tidak suka" dengan pemberian pivot di bagian tengah gambar dan memutarnya 180 derajat:

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

Merender dari kode

Anda juga dapat mengurangi ukuran APK dengan merender gambar secara prosedural. Perenderan prosedural mengosongkan ruang penyimpanan karena Anda tidak lagi menyimpan file gambar dalam APK.

Mengecilkan file PNG

Alat aapt dapat mengoptimalkan resource gambar yang ditempatkan di res/drawable/ dengan kompresi lossless selama proses build. Misalnya, alat aapt dapat mengonversi PNG warna asli yang tidak memerlukan lebih dari 256 warna menjadi PNG 8 bit dengan palet warna. Tindakan tersebut akan menghasilkan gambar dengan kualitas yang sama, tetapi dengan footprint memori yang lebih kecil.

aapt memiliki batasan berikut:

  • Alat aapt tidak memperkecil file PNG yang ada dalam folder asset/.
  • File gambar perlu menggunakan maksimal 256 warna agar alat aapt dapat mengoptimalkannya.
  • Alat aapt mungkin meng-inflate file PNG yang sudah dikompresi. Untuk mencegah hal ini, Anda dapat menggunakan tanda isCrunchPngs guna menonaktifkan proses ini untuk file PNG:
  • Kotlin

        buildTypes.all { isCrunchPngs = false }
        

    Groovy

        buildTypes.all { isCrunchPngs = false }
        

Mengompresi file PNG dan JPEG

Anda dapat mengurangi ukuran file PNG tanpa menurunkan kualitas gambar menggunakan alat seperti pngcrush, pngquant, atau zopflipng. Semua alat ini dapat mengurangi ukuran file PNG, tetapi tetap mempertahankan ketajaman kualitas gambar.

Alat pngcrush sangat efektif. Alat ini mengiterasi filter PNG dan parameter zlib (Deflate), menggunakan setiap kombinasi filter dan parameter untuk mengompresi gambar. Lalu, alat ini memilih konfigurasi yang menghasilkan output terkompresi yang paling kecil.

Untuk mengompresi file JPEG, Anda dapat menggunakan alat seperti packJPG dan guetzli.

Menggunakan format file WebP

Selain menggunakan file PNG atau JPEG, Anda juga dapat menggunakan format file WebP untuk gambar Anda. Format WebP memberikan kompresi dan transparansi lossy, seperti JPG dan PNG, dan dapat memberikan kompresi yang lebih baik daripada JPEG atau PNG.

Anda dapat mengonversi gambar BMP, JPG, PNG, atau GIF statis yang ada ke format WebP menggunakan Android Studio. Untuk informasi selengkapnya, lihat Membuat gambar WebP.

Menggunakan grafik vektor

Anda dapat menggunakan grafik vektor untuk membuat ikon dengan resolusi bebas dan media skalabel lainnya. Anda dapat menggunakan grafik ini untuk mengurangi footprint APK secara signifikan. Gambar vektor direpresentasikan di Android sebagai objek VectorDrawable. Dengan objek VectorDrawable, file berukuran 100 byte dapat menghasilkan gambar yang tajam seukuran layar.

Namun, perlu waktu yang jauh lebih lama bagi sistem untuk merender setiap objek VectorDrawable, dan gambar yang lebih besar memerlukan waktu yang lebih lama untuk ditampilkan di layar. Oleh karena itu, pertimbangkan untuk menggunakan grafik vektor ini hanya ketika menampilkan gambar berukuran kecil.

Untuk informasi selengkapnya tentang cara menangani objek VectorDrawable, lihat Drawable.

Menggunakan grafik vektor untuk gambar animasi

Jangan gunakan AnimationDrawable untuk membuat animasi frame per frame, karena Anda akan diharuskan menyertakan file bitmap terpisah untuk setiap frame animasi, yang akan memperbesar ukuran APK Anda.

Sebagai gantinya, gunakan AnimatedVectorDrawableCompat untuk membuat vektor drawable beranimasi.

Mengurangi kode native dan Java

Anda dapat menggunakan metode berikut untuk mengurangi ukuran codebase native dan Java di aplikasi.

Menghapus kode tidak perlu yang dihasilkan

Pastikan Anda memahami jejak kode apa pun yang dihasilkan secara otomatis. Misalnya, banyak fitur buffering protokol yang menghasilkan terlalu banyak metode dan class, yang dapat memperbesar ukuran aplikasi Anda dua atau tiga kali lipat.

Menghindari enumerasi (pencacahan)

Satu enum dapat menambahkan sekitar 1,0 hingga 1,4 KB ke file classes.dex aplikasi Anda. Penambahan ini dapat dengan cepat terakumulasi untuk sistem yang kompleks atau library bersama. Jika memungkinkan, pertimbangkan untuk menggunakan anotasi @IntDef dan penyingkatan kode untuk menghapus enumerasi dan mengubahnya menjadi bilangan bulat. Konversi jenis ini mempertahankan semua manfaat keamanan jenis dari enum.

Mengurangi ukuran biner native

Jika aplikasi menggunakan kode native dan Android NDK, Anda juga dapat mengurangi ukuran aplikasi versi rilis dengan mengoptimalkan kode Anda. Dua teknik ampuh ini dapat menghapus simbol debug dan tidak mengekstrak library native.

Menghapus simbol debug

Simbol debug dapat digunakan jika aplikasi sedang dalam pengembangan dan masih memerlukan proses debug. Gunakan alat arm-eabi-strip yang disediakan di Android NDK untuk menghapus simbol debug yang tidak diperlukan dari library native. Setelah itu, Anda dapat mengompilasi build rilis Anda.

Menghindari pengekstrakan library native

Saat membuat versi rilis aplikasi, kemas file .so yang tidak dikompresi di APK dengan menetapkan useLegacyPackaging ke false di file build.gradle.kts aplikasi Anda. Menonaktifkan tanda ini akan mencegah PackageManager menyalin file .so dari APK ke sistem file selama penginstalan. Metode ini membuat update aplikasi menjadi lebih kecil.

Mempertahankan beberapa APK berukuran kecil

APK dapat berisi konten yang didownload oleh pengguna tetapi tidak pernah digunakan, seperti bahasa tambahan atau resource per kepadatan layar. Untuk membantu memastikan download yang minimal bagi pengguna, upload aplikasi Anda ke Google Play menggunakan Android App Bundle. Dengan mengupload app bundle, Google Play dapat membuat dan menayangkan APK yang dioptimalkan untuk setiap konfigurasi perangkat pengguna, sehingga pengguna hanya mendownload kode dan resource yang diperlukan untuk menjalankan aplikasi. Anda tidak perlu lagi mem-build, menandatangani, dan mengelola beberapa APK untuk mendukung berbagai perangkat, dan pengguna akan mendapatkan hasil download yang lebih kecil dan optimal.

Jika Anda tidak memublikasikan aplikasi ke Google Play, Anda dapat membagi aplikasi menjadi beberapa APK, yang dibedakan oleh faktor seperti ukuran layar atau dukungan tekstur GPU.

Saat pengguna mendownload aplikasi, perangkat mereka menerima APK yang tepat berdasarkan fitur dan setelan perangkat. Dengan cara ini, perangkat tidak menerima aset untuk fitur yang tidak dimiliki perangkat. Misalnya, jika pengguna memiliki perangkat hdpi, mereka tidak memerlukan resource xxxhdpi yang mungkin Anda sertakan untuk perangkat dengan tampilan yang memiliki kepadatan lebih tinggi.

Untuk informasi selengkapnya, lihat Membuat beberapa APK dan Dukungan multi-APK.