Mengurangi ukuran aplikasi Anda

Banyak pengguna sering menghindari mendownload aplikasi yang terlalu besar, terutama di pasar negara berkembang yang kebanyakan perangkatnya mengandalkan jaringan 2G dan 3G yang tidak stabil atau menggunakan paket berdasarkan penggunaan per byte. Halaman ini menjelaskan cara mengurangi ukuran download aplikasi, yang memungkinkan lebih banyak pengguna untuk mendownload aplikasi Anda.

Mengupload aplikasi dengan Android App Bundle

Cara termudah untuk langsung mendapatkan penghematan ukuran aplikasi saat memublikasikan ke Google Play adalah dengan mengupload aplikasi sebagai Android App Bundle, yang merupakan format upload baru yang mencakup semua kompilasi kode dan resource aplikasi Anda, namun menyerahkan pembuatan dan penandatanganan APK ke Google Play.

Model penayangan aplikasi baru di Google Play, yang disebut Pengiriman Dinamis, menggunakan app bundle untuk membuat dan menayangkan APK yang dioptimalkan untuk tiap konfigurasi perangkat pengguna, sehingga pengguna hanya mendownload kode dan resource yang mereka butuhkan untuk menjalankan aplikasi Anda. Anda tidak perlu lagi membuat, menandatangani, dan mengelola banyak APK untuk mendukung perangkat yang berbeda, dan pengguna mendapatkan download yang lebih kecil dan lebih dioptimalkan.

Perlu diingat, karena Google Play menerapkan batasan ukuran download yang dikompresi sebesar 150 MB atau kurang untuk aplikasi yang dipublikasikan dengan app bundle, sebaiknya tetap terapkan pedoman yang dijelaskan di sini untuk mengurangi ukuran download aplikasi Anda sekecil mungkin.

Untuk aplikasi yang Anda publikasikan ke Google Play dengan mengupload APK yang ditandatangani, download yang dikompresi dibatasi ke 100 MB atau kurang.

Memahami struktur APK

Sebelum membahas cara mengurangi ukuran aplikasi Anda, ada baiknya untuk memahami struktur APK aplikasi terlebih dahulu. File APK terdiri dari arsip ZIP yang berisi semua file yang membentuk aplikasi Anda. File ini meliputi file kelas Java, file resource, dan file yang berisi kompilasi resource.

APK berisi direktori berikut:

  • META-INF/: Berisi file signature CERT.SF dan CERT.RSA, serta file manifes MANIFEST.MF.
  • assets/: Berisi aset aplikasi, yang dapat diambil oleh aplikasi menggunakan objek AssetManager.
  • res/: Berisi resource yang tidak dikompilasi ke dalam 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. Di antara file tersebut, hanya AndroidManifest.xml yang bersifat wajib.

  • resources.arsc: Berisi kompilasi resource. File ini berisi konten XML dari semua konfigurasi folder res/values/. Fitur paket mengekstrak konten XML ini, mengompilasikannya ke bentuk biner, dan mengarsipkan konten. Konten ini mencakup string dan gaya bahasa, serta lokasi ke konten yang tidak disertakan secara langsung di file resources.arsc, seperti gambar dan file tata letak.
  • classes.dex: Berisi kompilasi kelas dalam format file DEX yang dipahami oleh mesin virtual Dalvik/ART.
  • AndroidManifest.xml: Berisi file manifes Android inti. File ini mencakup nama, versi, hak akses, dan file referensi library aplikasi. File tersebut 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. Salah satu cara termudah memperkecil ukuran APK adalah dengan mengurangi jumlah dan ukuran resource yang ada. Secara khusus, Anda dapat menghapus resource yang tidak digunakan aplikasi lagi, dan Anda dapat menggunakan objek Drawable skalabel sebagai pengganti file gambar. Bagian ini membahas metode ini serta beberapa cara lain yang dapat Anda lakukan untuk mengurangi resource di aplikasi agar dapat mengurangi keseluruhan ukuran APK.

Menghapus resource yang tidak digunakan

Fitur lint, sebuah penganalisis kode statis yang disertakan di Android Studio, detects mendeteksi resource di folder res/ yang tidak direferensikan oleh kode Anda. Saat fitur lint menemukan resource yang mungkin tidak digunakan di project Anda, fitur akan menampilkan pesan seperti contoh di bawah.

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

Catatan: Fitur lint tidak memindai folder assets/, aset yang direferensikan melalui refleksi, atau file library yang Anda tautkan ke aplikasi. Selain itu, fitur tidak menghapus resource, namun hanya memberi tahu Anda keberadaannya.

Library yang Anda tambahkan ke kode dapat menyertakan resource yang tidak digunakan. Gradle dapat menghapus resource secara otomatis atas nama Anda jika Anda mengaktifkan shrinkResources di file build.gradle aplikasi.

    android {
        // Other settings

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

Untuk menggunakan shrinkResources, Anda harus mengaktifkan penciutan kode. Selama proses build, ProGuard terlebih dahulu menghapus kode yang tidak digunakan, dan mempertahankan resource yang tidak digunakan. Setelah itu, Gradle akan menghapus resource yang tidak digunakan.

Untuk mengetahui informasi selengkapnya tentang ProGuard dan cara lain yang digunakan Android Studio untuk membantu Anda mengurangi ukuran APK, lihat Menciutkan Kode dan Resource Anda.

Di Android Gradle Plugin 0.7 dan versi yang lebih tinggi, Anda dapat menyatakan konfigurasi yang didukung aplikasi. Gradle meneruskan informasi ke sistem build menggunakan ragam resConfig dan resConfigs, serta opsi defaultConfig. Lalu, sistem build mencegah resource dari konfigurasi lain yang tidak didukung agar tidak muncul di APK, mengurangi ukuran APK. Untuk mengetahui 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 menyempurnakan kegunaan dan fleksibilitas aplikasi. Misalnya, Anda mungkin mereferensikan Android Support Library untuk menyempurnakan pengalaman pengguna di perangkat dengan versi yang lebih lama, atau Anda dapat menggunakan Layanan Google Play untuk mengambil terjemahan otomatis untuk teks dalam aplikasi.

Jika library didesain 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.

Catatan: ProGuard dapat menghapus beberapa kode yang tidak diperlukan yang diimpor dengan library, namun tidak dapat menghapus dependensi internal yang besar pada library.

Hanya mendukung kepadatan tertentu

Android mendukung serangkaian perangkat yang besar, yang mencakup berbagai jenis kepadatan layar. Di Android 4.4 (API level 19) dan versi lebih tinggi, framework mendukung berbagai kepadatan: ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpi dan xxxhdpi. Meskipun Android mendukung semua kepadatan ini, Anda tidak perlu mengekspor aset raster ke setiap kepadatan.

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

Jika aplikasi memerlukan gambar yang diskalakan saja, Anda dapat menghemat lebih banyak ruang dengan memilih satu varian gambar dalam drawable-nodpi/. Sebaiknya setiap aplikasi menyertakan setidaknya satu varian gambar xxhdpi.

Untuk mengetahui 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 menggambar gambar pada waktu proses berjalan secara dinamis. Objek Drawable (<shape> dalam XML) dapat menggunakan sebagian kecil ruang di APK. Selain itu, objek Drawable XML menghasilkan gambar monokromatik yang sesuai dengan panduan desain material.

Menggunakan kembali resource

Anda dapat menyertakan resource terpisah untuk variasi sebuah gambar, misalnya versi diwarnai, diberi bayangan, atau diputar. Namun, sebaiknya Anda menggunakan kembali kumpulan resource yang sama, menyesuaikannya sesuai kebutuhan pada waktu proses berjalan.

Android menyediakan beberapa utilitas untuk mengubah warna aset, baik menggunakan atribut android:tint dan tintMode di Android 5.0 (API level 21) dan versi yang lebih tinggi. Untuk versi platform yang lebih rendah, gunakan kelas ColorFilter.

Anda juga dapat menghilangkan resource yang setara dengan resource lain. 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

Fitur aapt dapat mengoptimalkan resource gambar yang ditempatkan di res/drawable/ dengan kompresi lossless selama proses build. Misalnya, fitur 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.

Perlu diingat bahwa aapt memiliki batasan berikut:

  • Fitur aapt tidak memperkecil file PNG yang ada dalam folder asset/.
  • File gambar perlu menggunakan 256 warna atau lebih sedikit untuk fitur aapt guna mengoptimalkannya.
  • Fitur aapt mungkin dapat memperbesar file PNG yang telah dikompresi. Anda dapat mencegah hal ini dengan menggunakan tanda cruncherEnabled di Gradle guna menonaktifkan proses ini untuk file PNG:
    aaptOptions {
        cruncherEnabled = false
    }
    

Mengompresi file PNG dan JPEG

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

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

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

Menggunakan format file WebP

Selain menggunakan file PNG atau JPEG, Anda juga dapat menggunakan format file WebP untuk gambar Anda, dengan target penggunaan di Android 3.2 (API level 13) dan yang lebih tinggi. Format WebP menyediakan kompresi lossy (seperti JPEG) serta transparansi (seperti PNG) tetapi bisa 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 mengetahui informasi selengkapnya, lihat Membuat Gambar WebP Menggunakan Android Studio.

Catatan: Google Play menerima APK hanya jika ikon peluncur menggunakan format PNG.

Menggunakan grafik vektor

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

Namun, diperlukan waktu yang lama agar sistem merender tiap 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 yang kecil.

Untuk informasi selengkapnya mengenai cara menggunakan objek VectorDrawable, lihat Menggunakan Resource yang Dapat Digambar.

Menggunakan grafik vektor untuk gambar animasi

Jangan gunakan AnimationDrawable untuk membuat animasi frame by frame karena Anda diharuskan menyertakan file bitmap terpisah untuk tiap frame animasi, yang akan memperbesar ukuran APK secara drastis.

Sebagai gantinya, Anda sebaiknya menggunakan AnimatedVectorDrawableCompat untuk membuat vektor animasi yang dapat digambar.

Mengurangi kode Java dan native

Ada beberapa metode yang dapat Anda gunakan untuk mengurangi ukuran codebase native dan Java di aplikasi.

Menghapus kode tidak perlu yang dihasilkan

Pastikan Anda memahami footprint kode apa pun yang dihasilkan secara otomatis. Misalnya, banyak fitur buffering protokol menghasilkan terlalu banyak metode dan kelas, yang dapat memperbesar ukuran aplikasi Anda dua kali lipat bahkan lebih.

Menghindari enumerasi (pencacahan)

Satu enum bisa menambahkan sekitar 1,0 hingga 1,4 KB ukuran 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 ProGuard untuk menghapus enumerasi dan mengubahnya menjadi bilangan bulat. Konversi jenis ini mempertahankan semua manfaat keamanan 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 fitur arm-eabi-strip, yang disediakan di Android NDK, untuk menghapus simbol debug yang tidak diperlukan dari library native. Setelah itu, Anda bisa mengompilasi build rilis Anda.

Menghindari pengekstrakan library native

Saat membuat aplikasi versi rilis, buat paket file .so yang tidak terkompresi di APK dengan menyetel android:extractNativeLibs="false" di elemen <application> manifes aplikasi Anda. Menonaktifkan tanda ini akan mencegah PackageManager agar tidak menyalin file .so dari APK ke sistem file selama penginstalan dan memiliki manfaat tambahan untuk memperkecil update aplikasi Anda.

Mempertahankan beberapa APK berukuran kecil

APK dapat berisi konten yang didownload oleh pengguna namun tidak pernah digunakan, seperti bahasa tambahan atau resource per kepadatan layar. Untuk memastikan download yang minimal bagi pengguna, sebaiknya upload aplikasi Anda ke Google Play menggunakan Android App Bundle. Mengupload app bundle memungkinkan Google Play membuat dan menayangkan APK yang dioptimalkan untuk tiap konfigurasi perangkat pengguna, sehingga pengguna hanya mendownload kode dan resource yang mereka butuhkan untuk menjalankan aplikasi Anda. Anda tidak perlu lagi membuat, menandatangani, dan mengelola banyak APK untuk mendukung perangkat yang berbeda, dan pengguna mendapatkan download yang lebih kecil dan lebih dioptimalkan.

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 kepadatan yang lebih tinggi.

Untuk mengetahui informasi selengkapnya, lihat Mengonfigurasi Pembagian APK dan Memelihara Beberapa APK.