Внимание: с августа 2021 года все новые приложения должны публиковаться в виде пакетов приложений (App Bundle). Если вы публикуете приложение в Google Play, создайте и загрузите пакет приложений Android App Bundle . При этом Google Play автоматически генерирует и предоставляет оптимизированные APK-файлы для конфигурации устройства каждого пользователя, чтобы он мог загрузить только тот код и ресурсы, которые необходимы для запуска вашего приложения. Публикация нескольких APK-файлов полезна, если вы публикуете приложение в магазине, не поддерживающем формат AAB. В этом случае вам необходимо самостоятельно создавать, подписывать и управлять каждым APK-файлом.
Хотя лучше по возможности создавать единый APK-файл для поддержки всех целевых устройств, это может привести к очень большому размеру APK-файла из-за файлов, поддерживающих несколько двоичных интерфейсов приложений (ABI). Один из способов уменьшить размер APK-файла — создать несколько APK-файлов , содержащих файлы для разных ABI.
Gradle может создавать отдельные APK-файлы, содержащие только код и ресурсы, специфичные для каждого ABI. На этой странице описано, как настроить сборку для создания нескольких APK-файлов. Если вам нужно создать разные версии приложения, не основанные на ABI, используйте варианты сборки .
Настройте сборку для нескольких APK
Чтобы настроить сборку для нескольких APK, добавьте блок splits в файл build.gradle на уровне модуля. В блоке splits укажите блок abi , который определяет, как Gradle будет генерировать APK для каждого ABI.
Настройте несколько APK для ABI
Чтобы создать отдельные APK для разных ABI, добавьте блок abi внутрь блока splits . В блоке abi укажите список желаемых ABI.
Для настройки нескольких APK на один ABI используются следующие параметры Gradle DSL:
-
enableдля Groovy илиisEnableдля скрипта Kotlin - Если этому элементу присвоено значение
true, Gradle сгенерирует несколько APK-файлов на основе определенных вами ABI. Значение по умолчанию —false. -
exclude - Указывает список ABI, разделённых запятыми, для которых Gradle не должен генерировать отдельные APK. Используйте
excludeесли вы хотите генерировать APK для большинства ABI, но хотите исключить несколько ABI, которые ваше приложение не поддерживает. -
reset() Очищает список ABI по умолчанию. Используйте только в сочетании с элементом
includeдля указания ABI, которые вы хотите добавить.В следующем фрагменте кода список ABI задается только для
x86иx86_64путем вызоваreset()для очистки списка, а затем использованияinclude: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- Указывает список ABI, разделённый запятыми, для которых Gradle должен сгенерировать APK. Используйте только в сочетании с
reset()для указания точного списка ABI. -
universalApkдля Groovy илиisUniversalApkдля скрипта Kotlin Если задано
true, Gradle генерирует универсальный APK в дополнение к APK для каждого ABI. Универсальный APK содержит код и ресурсы для всех ABI в одном APK. Значение по умолчанию —false.
В следующем примере генерируется отдельный APK для каждого ABI: x86 и x86_64 . Это делается с помощью reset() , который сначала использует пустой список ABI, а затем include список ABI, каждый из которых получает APK.
Круто
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 you only // want APKs for x86 and x86_64. // Resets the list of ABIs for Gradle to create APKs for to none. reset() // Specifies a list of ABIs for Gradle to create APKs for. include "x86", "x86_64" // Specifies that you don't want to also generate a universal APK that includes all ABIs. universalApk false } } }
Котлин
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 you only // want APKs for x86 and x86_64. // Resets the list of ABIs for Gradle to create APKs for to none. reset() // Specifies a list of ABIs for Gradle to create APKs for. include("x86", "x86_64") // Specifies that you don't want to also generate a universal APK that includes all ABIs. isUniversalApk = false } } }
Список поддерживаемых ABI см. в разделе Поддерживаемые ABI .
Проекты без нативного/C++ кода
Для проектов без собственного кода C++ панель «Варианты сборки» имеет два столбца: «Модуль» и «Активный вариант сборки» , как показано на рисунке 1.

Рисунок 1. Панель «Варианты сборки» содержит два столбца для проектов без собственного кода C++.
Значение «Активный вариант сборки» для модуля определяет вариант сборки, который будет развёрнут и виден в редакторе. Для переключения между вариантами щёлкните по ячейке «Активный вариант сборки» для модуля и выберите нужный вариант из списка.
Проекты с нативным/C++ кодом
Для проектов с собственным кодом C++ панель «Варианты сборки» имеет три столбца: «Модуль» , «Активный вариант сборки » и «Активный ABI» , как показано на рисунке 2.
Рисунок 2. Панель «Варианты сборки» добавляет столбец «Активный ABI» для проектов с собственным кодом C++.
Значение параметра Active Build Variant для модуля определяет вариант сборки, который будет развёрнут и виден в редакторе. Для нативных модулей значение Active ABI определяет ABI, используемый редактором, но не влияет на то, что именно будет развёрнуто.
Чтобы изменить тип сборки или ABI:
- Щелкните ячейку столбца «Активный вариант сборки» или «Активный ABI» .
- Выберите нужный вариант или ABI из списка. Новая синхронизация запустится автоматически.
Изменение любого столбца для приложения или модуля библиотеки применяет изменение ко всем зависимым строкам.
Настроить версионирование
По умолчанию, когда Gradle генерирует несколько APK-файлов, каждый APK-файл имеет одинаковую информацию о версии, указанную в файле build.gradle или build.gradle.kts на уровне модуля. Поскольку в Google Play Store не допускается создание нескольких APK-файлов одного и того же приложения с одинаковой информацией о версии, перед загрузкой в Play Store необходимо убедиться, что каждый APK-файл имеет уникальный versionCode .
Вы можете настроить файл build.gradle на уровне модуля, чтобы переопределить versionCode для каждого APK. Создав сопоставление, назначающее уникальное числовое значение для каждого ABI, для которого вы настраиваете несколько APK, вы можете переопределить выходной код версии значением, которое объединяет код версии, определенный в блоке defaultConfig или productFlavors с числовым значением, назначенным ABI.
В следующем примере APK для x86 ABI получает versionCode 2004, а x86_64 ABI получает versionCode 3004.
Назначение кодов версий большими шагами, например, 1000, позволяет впоследствии назначать уникальные коды версий при необходимости обновления приложения. Например, если defaultConfig.versionCode при следующем обновлении принимает значение 5, Gradle присваивает versionCode 2005 APK-файлу x86 и 3005 APK-файлу x86_64 .
Совет: если ваша сборка включает универсальный APK, назначьте ему versionCode ниже, чем у любого другого APK. Поскольку Google Play Store устанавливает версию вашего приложения, совместимую с целевым устройством и имеющую наибольший versionCode , назначение меньшего versionCode универсальному APK гарантирует, что Google Play Store попытается установить один из ваших APK, прежде чем вернуться к универсальному APK. Следующий пример кода решает эту проблему, не переопределяя versionCode универсального APK по умолчанию.
Круто
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] 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 doesn't override the version code for universal APKs. // However, because you 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 causes Gradle to use the value of variant.versionCode for the APK. output.versionCodeOverride = baseAbiVersionCode * 1000 + variant.versionCode } } }
Котлин
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) 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 doesn't override the version code for universal APKs. // However, because you 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)) } } } }
Дополнительные примеры альтернативных схем кодирования версий см. в разделе Назначение кодов версий .
Создание нескольких APK-файлов
После настройки файла build.gradle или build.gradle.kts на уровне модуля для сборки нескольких APK-файлов нажмите «Сборка» > «Сборка APK», чтобы собрать все APK-файлы для текущего выбранного модуля на панели «Проект» . Gradle создаёт APK-файлы для каждого ABI в каталоге build/outputs/apk/ проекта.
Gradle создает APK для каждого ABI, для которого вы настраиваете несколько APK.
Например, следующий фрагмент build.gradle позволяет собирать несколько APK для ABI x86 и x86_64 :
Круто
... splits { abi { enable true reset() include "x86", "x86_64" } }
Котлин
... splits { abi { isEnable = true reset() include("x86", "x86_64") } }
Вывод примера конфигурации включает следующие 4 APK:
-
app-X86-release.apk: Содержит код и ресурсы дляx86ABI. -
app-X86_64-release.apk: Содержит код и ресурсы дляx86_64ABI.
При сборке нескольких APK на основе ABI Gradle генерирует APK, включающий код и ресурсы для всех ABI, только если вы указали universalApk true в блоке splits.abi в файле build.gradle (для Groovy) или isUniversalApk = true в блоке splits.abi в файле build.gradle.kts (для скрипта Kotlin).
Формат имени APK-файла
При сборке нескольких APK Gradle генерирует имена файлов APK по следующей схеме:
modulename - ABI - buildvariant .apk
Компоненты схемы:
-
modulename - Указывает имя создаваемого модуля.
-
ABI Если включено несколько APK для ABI, указывает ABI для APK, например
x86.-
buildvariant - Указывает вариант сборки, который будет создан, например
debug.