Jika Anda memublikasikan aplikasi ke Google Play, sebaiknya build dan upload Android App Bundle. Setelah Anda melakukannya, Google Play akan otomatis membuat dan menayangkan APK yang dioptimalkan untuk setiap konfigurasi perangkat pengguna, sehingga pengguna hanya mendownload kode dan resource yang diperlukan untuk menjalankan aplikasi Anda. Memublikasikan beberapa APK akan berguna jika Anda memublikasikan ke store yang tidak mendukung format AAB. Dalam hal ini, Anda harus membuat, menandatangani, dan mengelola sendiri setiap APK.
Meskipun, jika memungkinkan, sebaiknya Anda membuat satu APK untuk mendukung semua perangkat target, hal tersebut dapat menghasilkan APK yang sangat besar karena adanya file yang diperlukan untuk mendukung beberapa kepadatan layar atau Antarmuka Biner Aplikasi (ABI). Salah satu cara untuk mengurangi ukuran APK adalah dengan membuat multi-APK yang berisi file untuk kepadatan layar atau ABI tertentu.
Gradle dapat membuat APK terpisah yang hanya berisi kode dan resource khusus untuk setiap kepadatan atau ABI. Halaman ini menjelaskan cara mengonfigurasi build Anda untuk membuat multi-APK. Jika perlu membuat beberapa versi lain aplikasi Anda yang tidak berdasarkan kepadatan layar atau ABI, Anda dapat menggunakan varian build.
Mengonfigurasi build untuk multi-APK
Guna mengonfigurasi build Anda untuk multi-APK, tambahkan blok splits
ke file build.gradle
tingkat modul Anda. Dalam blok splits
, sediakan blok density
yang menentukan cara Gradle akan menghasilkan APK untuk setiap kepadatan, atau blok abi
yang menentukan cara Gradle akan menghasilkan APK untuk setiap ABI. Anda dapat menyediakan blok kepadatan dan ABI, sedangkan sistem build akan membuat APK untuk setiap kombinasi kepadatan dan ABI.
Mengonfigurasi multi-APK untuk kepadatan layar
Untuk membuat APK terpisah bagi kepadatan layar yang berbeda, tambahkan blok density
di dalam blok splits
Anda. Di blok density
Anda, cantumkan kepadatan layar yang diinginkan dan ukuran layar yang kompatibel. Daftar ukuran layar yang kompatibel hanya boleh digunakan jika Anda memerlukan elemen <compatible-screens>
spesifik di setiap manifes APK.
Opsi Gradle DSL berikut digunakan untuk mengonfigurasi multi-APK untuk kepadatan layar:
-
enable
-
Jika Anda menetapkan elemen ini ke
true
, Gradle akan menghasilkan multi-APK berdasarkan kepadatan layar yang Anda tentukan. Nilai defaultnya adalahfalse
. -
exclude
-
Menentukan daftar yang dipisahkan koma untuk kepadatan yang APK terpisahnya tidak perlu dihasilkan oleh Gradle. Gunakan
exclude
jika Anda ingin membuat APK untuk sebagian besar kepadatan, tetapi Anda perlu mengecualikan sejumlah kepadatan yang tidak didukung aplikasi Anda. -
reset()
-
Mengosongkan daftar default kepadatan layar. Gunakan opsi ini hanya jika dikombinasikan dengan elemen
include
untuk menentukan kepadatan yang ingin Anda tambahkan. Cuplikan berikut menetapkan daftar kepadatan untukldpi
danxxhdpi
saja dengan memanggilreset()
untuk mengosongkan daftar, kemudian menggunakaninclude
.reset() // Clears the default list from all densities to no densities. include "ldpi", "xxhdpi" // Specifies the two densities we want to generate APKs for.
-
include
-
Menentukan daftar yang dipisahkan koma untuk kepadatan yang APK-nya perlu dihasilkan oleh Gradle. Gunakan opsi ini hanya jika dikombinasikan dengan
reset()
untuk menentukan daftar kepadatan pasti. -
compatibleScreens
-
Menentukan daftar yang dipisahkan koma untuk ukuran layar yang kompatibel. Opsi ini akan memasukkan node
<compatible-screens>
yang cocok dalam manifes untuk setiap APK. Setelan ini memberikan cara mudah untuk mengelola kepadatan layar serta ukuran layar di bagianbuild.gradle
yang sama. Namun, penggunaan<compatible-screens>
dapat membatasi jenis perangkat yang dapat menjalankan aplikasi Anda. Cara alternatif untuk mendukung berbagai ukuran layar dapat ditemukan di Mendukung Banyak Layar.
Karena setiap APK yang berdasarkan kepadatan layar akan menyertakan tag <compatible-screens>
dengan pembatasan khusus terkait jenis layar mana yang didukung APK, meskipun Anda memublikasikan sejumlah APK, beberapa perangkat baru tidak akan cocok dengan beberapa filter APK Anda. Oleh karena itu, Gradle akan selalu menghasilkan APK universal tambahan yang berisi aset untuk semua kepadatan layar dan tidak menyertakan tag <compatible-screens>
. Sebaiknya Anda memublikasikan APK universal ini bersama APK untuk setiap kepadatan guna menyediakan penggantian bagi perangkat yang tidak cocok dengan APK yang menyertakan tag <compatible-screens>
.
Contoh berikut ini akan menghasilkan APK terpisah untuk setiap kepadatan layar yang tercantum dalam Rentang layar yang didukung, kecuali ldpi
, xxhdpi
, dan xxxhdpi
. Hal ini dilakukan
dengan menggunakan exclude
untuk menghapus tiga kepadatan dari daftar default
semua kepadatan.
Groovy
android { ... splits { // Configures multiple APKs based on screen density. density { // Configures multiple APKs based on screen density. enable true // Specifies a list of screen densities Gradle should not create multiple APKs for. exclude "ldpi", "xxhdpi", "xxxhdpi" // Specifies a list of compatible screen size settings for the manifest. compatibleScreens 'small', 'normal', 'large', 'xlarge' } } }
Kotlin
android { ... splits { // Configures multiple APKs based on screen density. density { // Configures multiple APKs based on screen density. isEnable = true // Specifies a list of screen densities Gradle should not create multiple APKs for. exclude("ldpi", "xxhdpi", "xxxhdpi") // Specifies a list of compatible screen size settings for the manifest. compatibleScreens("small", "normal", "large", "xlarge") } } }
Untuk mengetahui daftar nama kepadatan dan nama ukuran layar, baca Cara Mendukung Banyak Layar. Untuk detail selengkapnya tentang mendistribusikan aplikasi Anda ke perangkat dan jenis layar tertentu, lihat Mendistribusikan ke Layar Tertentu.
Mengonfigurasi multi-APK untuk ABI
Guna membuat APK terpisah untuk ABI berbeda, tambahkan blok abi
di dalam blok
splits
Anda. Dalam blok abi
Anda, cantumkan ABI yang diinginkan.
Opsi Gradle DSL berikut digunakan untuk mengonfigurasi multi-APK untuk setiap ABI:
-
enable
- Jika Anda menetapkan elemen ini ke
true
, Gradle akan menghasilkan multi-APK berdasarkan ABI yang ditetapkan. Nilai defaultnya adalahfalse
-
exclude
-
Menentukan daftar yang dipisahkan koma untuk ABI yang APK terpisahnya tidak perlu dihasilkan oleh Gradle. Gunakan
exclude
jika Anda ingin membuat APK untuk sebagian besar ABI, tetapi Anda perlu mengecualikan beberapa ABI yang tidak didukung oleh aplikasi Anda. -
reset()
-
Mengosongkan daftar default untuk ABI. Gunakan opsi ini hanya jika dikombinasikan dengan elemen
include
untuk menentukan ABI yang ingin Anda tambahkan. Cuplikan berikut menetapkan daftar ABI untukx86
danx86_64
saja dengan memanggilreset()
untuk mengosongkan daftar, lalu menggunakaninclude
:reset() // Clears the default list from all ABIs to no ABIs. include "x86", "x86_64" // Specifies the two ABIs we want to generate APKs for.
-
include
-
Menentukan daftar yang dipisahkan koma untuk ABI yang APK-nya perlu dihasilkan oleh Gradle. Gunakan opsi ini hanya jika dikombinasikan dengan
reset()
untuk menentukan daftar pasti ABI. -
universalApk
-
Jika
true
, Gradle akan menghasilkan APK universal selain APK untuk setiap ABI. APK universal berisi kode dan resource untuk semua ABI dalam satu APK. Nilai defaultnya adalahfalse
. Perlu diperhatikan bahwa opsi ini hanya tersedia di bloksplits.abi
. Saat mem-build beberapa APK berdasarkan kepadatan layar, Gradle akan selalu menghasilkan APK universal yang berisi kode dan resource untuk semua kepadatan layar.
Contoh berikut akan menghasilkan APK terpisah untuk setiap ABI: x86
dan x86_64
. Hal ini dilakukan dengan menggunakan reset()
untuk memulai dengan daftar ABI kosong, diikuti oleh include
dengan daftar
ABI yang masing-masing akan mendapatkan APK.
Groovy
android { ... splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. enable true // By default all ABIs are included, so use reset() and include to specify that we only // want APKs for x86 and x86_64. // Resets the list of ABIs that Gradle should create APKs for to none. reset() // Specifies a list of ABIs that Gradle should create APKs for. include "x86", "x86_64" // Specifies that we do not want to also generate a universal APK that includes all ABIs. universalApk false } } }
Kotlin
android { ... splits { // Configures multiple APKs based on ABI. abi { // Enables building multiple APKs per ABI. isEnable = true // By default all ABIs are included, so use reset() and include to specify that we only // want APKs for x86 and x86_64. // Resets the list of ABIs that Gradle should create APKs for to none. reset() // Specifies a list of ABIs that Gradle should create APKs for. include("x86", "x86_64") // Specifies that we do not want to also generate a universal APK that includes all ABIs. isUniversalApk = false } } }
Untuk daftar ABI yang didukung, lihat ABI yang Didukung.
mips, mips64, dan armeabi
Plugin Android untuk Gradle 3.1.0 dan yang lebih baru tidak lagi menghasilkan APK untuk ABI berikut secara default: mips
, mips64
, dan armeabi
. Hal itu karena NDK r17 dan yang lebih tinggi tidak lagi menyertakan ABI ini sebagai target yang didukung.
Sebaiknya periksa Konsol Google Play terlebih dulu untuk memastikan bahwa Anda memiliki pengguna yang mendownload APK aplikasi Anda yang menargetkan ABI ini. Jika tidak, sebaiknya Anda menghapusnya dari build Anda. Jika ANda ingin terus membuat APK yang menargetkan
ABI ini, sebaiknya menggunakan
NDK r16b atau yang lebih rendah, tetapkan ABI dan
varian build aktif, serta tentukan ABI dalam file
build.gradle
Anda, seperti yang ditunjukkan di bawah:
Groovy
splits { abi { include 'armeabi', 'mips', 'mips64' ... } }
Kotlin
splits { abi { include ("armeabi", "mips", "mips64") ... } }
Masalah Umum: Jika menggunakan Plugin Android untuk Gradle 3.0.1 atau yang lebih rendah
dengan NDK r17 atau yang lebih baru, Anda mungkin mendapatkan error berikut:
Error:ABIs [mips64, armeabi, mips] are not supported for platform.
Hal itu karena versi lama plugin ini masih menyertakan ABI yang secara default tidak didukung jika Anda membuat
APK untuk setiap ABI. Untuk mengatasi masalah ini,
update plugin
ke versi terbaru, atau, di file build.gradle
aplikasi Anda, reset daftar default plugin untuk ABI dan hanya sertakan ABI yang didukung
yang Anda inginkan, seperti ditunjukkan di bawah:
Groovy
... splits { abi { ... reset() include "x86", "armeabi-v7a", "arm64-v8a", "x86_64" } }
Kotlin
... splits { abi { ... reset() include("x86", "armeabi-v7a", "arm64-v8a", "x86_64") } }
Project tanpa kode native/C++
Panel Build Variants memiliki dua kolom: Module dan Active Build Variant. Nilai Active Build Variant untuk modul menentukan varian build yang akan di-deploy dan terlihat di editor.
Gambar 1: Panel Build Variants memiliki dua kolom untuk project yang tidak memiliki kode native/C++
Untuk beralih antarvarian, klik sel Active Build Variant untuk modul dan pilih varian yang diinginkan dari kolom daftar.
Project dengan kode native/C++
Panel Build Variants memiliki tiga kolom: Module, Active Build Variant, dan Active ABI. Nilai Active Build Variant untuk modul menentukan varian build yang akan di-deploy dan terlihat di editor. Untuk modul native, nilai Active ABI menentukan ABI yang akan digunakan editor, tetapi tidak memengaruhi apa yang di-deploy.
Gambar 2: Panel Build Variants menambahkan kolom Active ABI untuk project dengan kode native/C++
Untuk mengubah jenis build atau ABI, klik sel untuk kolom Active Build Variant atau Active ABI dan pilih varian atau ABI yang diinginkan dari kolom daftar. Sinkronisasi baru akan otomatis berjalan. Mengubah kolom untuk aplikasi maupun modul library akan menerapkan perubahan untuk semua baris dependen.
Mengonfigurasi pembuatan versi
Secara default, saat Gradle menghasilkan multi-APK, setiap APK akan memiliki informasi versi yang sama, seperti yang ditentukan dalam file build.gradle
tingkat modul. Karena Google Play Store tidak mengizinkan multi-APK untuk satu aplikasi jika semuanya memiliki informasi versi yang sama, Anda harus memastikan setiap APK memiliki versionCode
yang unik sebelum menguploadnya ke Play Store.
Anda dapat mengonfigurasi file build.gradle
tingkat modul untuk mengganti versionCode
setiap APK. Dengan membuat pemetaan yang menetapkan nilai numerik unik untuk setiap ABI dan kepadatan yang multi-APK-nya Anda konfigurasi, Anda dapat mengganti kode versi output dengan nilai yang menggabungkan kode versi yang ditentukan dalam blok defaultConfig
atau productFlavors
dengan nilai numerik yang ditetapkan untuk kepadatan atau ABI.
Pada contoh berikut, APK untuk ABI x86
akan mendapatkan versionCode
2004 dan ABI x86_64
akan mendapatkan 3004. Menetapkan kode versi dalam penambahan besar, seperti 1000, memungkinkan Anda untuk menetapkan kode versi unik nantinya jika Anda perlu mengupdate aplikasi Anda. Misalnya, jika defaultConfig.versionCode
melakukan iterasi ke 5 pada update berikutnya, Gradle akan menetapkan versionCode
2005 ke APK x86
dan 3005 ke APK x86_64
.
Tips: Jika build Anda menyertakan APK universal, Anda harus menetapkan versionCode
yang lebih rendah daripada APK lain mana pun ke build.
Karena Google Play Store menginstal versi aplikasi Anda yang kompatibel dengan perangkat target dan yang memiliki versionCode
tertinggi, menetapkan versionCode
yang lebih rendah ke APK universal akan memastikan bahwa Google Play Store mencoba menginstal salah satu APK Anda sebelum menggantinya ke APK universal. Kode contoh berikut ini menangani
hal ini tanpa mengganti versionCode
default APK universal.
Groovy
android { ... defaultConfig { ... versionCode 4 } splits { ... } } // Map for the version code that gives each ABI a value. ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3] // For per-density APKs, create a similar map like this: // ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3] import com.android.build.OutputFile // For each APK output variant, override versionCode with a combination of // ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode // is equal to defaultConfig.versionCode. If you configure product flavors that // define their own versionCode, variant.versionCode uses that value instead. android.applicationVariants.all { variant -> // Assigns a different version code for each output APK // other than the universal APK. variant.outputs.each { output -> // Stores the value of ext.abiCodes that is associated with the ABI for this variant. def baseAbiVersionCode = // Determines the ABI for this variant and returns the mapped value. project.ext.abiCodes.get(output.getFilter(OutputFile.ABI)) // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, // the following code does not override the version code for universal APKs. // However, because we want universal APKs to have the lowest version code, // this outcome is desirable. if (baseAbiVersionCode != null) { // Assigns the new version code to versionCodeOverride, which changes the version code // for only the output APK, not for the variant itself. Skipping this step simply // causes Gradle to use the value of variant.versionCode for the APK. output.versionCodeOverride = baseAbiVersionCode * 1000 + variant.versionCode } } }
Kotlin
android { ... defaultConfig { ... versionCode = 4 } splits { ... } } // Map for the version code that gives each ABI a value. val abiCodes = mapOf("armeabi-v7a" to 1, "x86" to 2, "x86_64" to 3) // For per-density APKs, create a similar map like this: // val densityCodes = mapOf("mdpi" to 1, "hdpi" to 2, "xhdpi" to 3) import com.android.build.api.variant.FilterConfiguration.FilterType.* // For each APK output variant, override versionCode with a combination of // abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode // is equal to defaultConfig.versionCode. If you configure product flavors that // define their own versionCode, variant.versionCode uses that value instead. androidComponents { onVariants { variant -> // Assigns a different version code for each output APK // other than the universal APK. variant.outputs.forEach { output -> val name = output.filters.find { it.filterType == ABI }?.identifier // Stores the value of abiCodes that is associated with the ABI for this variant. val baseAbiCode = abiCodes[name] // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes, // the following code does not override the version code for universal APKs. // However, because we want universal APKs to have the lowest version code, // this outcome is desirable. if (baseAbiCode != null) { // Assigns the new version code to output.versionCode, which changes the version code // for only the output APK, not for the variant itself. output.versionCode.set(baseAbiCode * 1000 + (output.versionCode.get() ?: 0)) } } } }
Untuk contoh skema kode versi alternatif lainnya, lihat Menetapkan kode versi.
Membuat multi-APK
Setelah Anda mengonfigurasi file build.gradle
tingkat modul untuk membuat multi-APK, klik Build > Build APK untuk membuat semua APK bagi modul yang saat ini dipilih di panel Project. Gradle membuat APK untuk setiap kepadatan atau ABI ke direktori build/outputs/apk/
project.
Gradle akan membuat APK untuk setiap kepadatan atau ABI yang multi APK-nya Anda konfigurasi.
Jika Anda mengaktifkan multi-APK untuk kepadatan dan ABI, Gradle akan membuat APK untuk setiap kombinasi kepadatan dan ABI. Misalnya, cuplikan build.gradle
berikut memungkinkan pembuatan multi-APK untuk kepadatan mdpi dan hdpi, serta ABI x86 dan x86_64.
Groovy
... splits { density { enable true reset() include "mdpi", "hdpi" } abi { enable true reset() include "x86", "x86_64" } }
Kotlin
... splits { density { enable true reset() include "mdpi", "hdpi" } abi { enable true reset() include "x86", "x86_64" } }
Output dari contoh konfigurasi ini mencakup 4 APK berikut:
app-hdpiX86-release.apk
: Berisi kode dan resource untuk kepadatan hdpi dan ABI x86 saja.app-hdpiX86_64-release.apk
: Berisi kode dan resource untuk kepadatan hdpi dan ABI x86_64 saja.app-mdpiX86-release.apk
: Berisi kode dan resource untuk kepadatan mdpi dan ABI x86 saja.app-mdpiX86_64-release.apk
: Berisi kode dan resource untuk kepadatan mdpi dan ABI x86_64 saja.
Saat membuat multi-APK berdasarkan kepadatan layar, Gradle akan selalu menghasilkan APK universal yang mencakup kode dan resource untuk semua kepadatan, selain APK untuk setiap kepadatan. Saat membuat multi-APK berdasarkan ABI, Gradle hanya akan menghasilkan APK yang mencakup kode dan resource untuk semua ABI jika Anda menentukan universalApk true
dalam blok splits.abi
pada file build.gradle
Anda.
Format nama file APK
Saat membuat multi-APK, Gradle menggunakan nama file APK yang menggunakan skema berikut:
modulename-screendensityABI-buildvariant.apk
Komponen skemanya adalah:
-
modulename
- Menentukan nama modul yang dibuat.
-
screendensity
- Menentukan kepadatan layar untuk APK, misalnya "mdpi", jika multi-APK untuk kepadatan layar diaktifkan.
-
ABI
-
Menentukan ABI untuk APK, misalnya "x86", jika multi-APK untuk ABI diaktifkan. Jika multi-APK untuk kepadatan layar dan juga ABI diaktifkan, Gradle akan merangkai nama kepadatan dengan nama ABI, misalnya "mdpiX86". Jika
universalApk
diaktifkan untuk APK per ABI, Gradle akan menggunakan "universal" sebagai bagian ABI dari nama file APK universal. -
buildvariant
- Menentukan varian build yang sedang dibuat, misalnya "debug".
Misalnya, saat membuat APK kepadatan layar mdpi untuk versi debug "myApp", nama file APK-nya adalah myApp-mdpi-debug.apk
. Versi rilis "myApp" yang dikonfigurasi guna membuat multi-APK untuk kepadatan layar mdpi dan ABI x86 memiliki nama file APK myApp-mdpiX86-release.apk
.