Соберите подписанный релизный бандл
Задайте ID приложения
В
app/build.gradle.ktsзначениеapplicationIdвdefaultConfigопределяет приложение в Google Play и не может измениться после первой загрузки.namespaceотносится только к коду и может отличаться.Соберите в Android Studio
Выберите Build → Generate Signed Bundle/APK, затем Android App Bundle, укажите хранилище и ключ (или Create new), вариант сборки release и нажмите Create.
Или из командной строки
Когда подпись настроена в Gradle (следующий раздел), выполните задачу ниже. Бандл сохраняется в
app/build/outputs/bundle/release/.
./gradlew bundleReleaseПеред загрузкой установите вариант release на устройство. Ошибки из-за R8 или настроек, действующих только в release, при запуске debug не проявляются:
./gradlew installReleaseКлюч загрузки и подписание приложений в Google Play
Новые приложения обязаны использовать подписание в Google Play: ключ подписи приложения хранит Google, а каждую загрузку вы подписываете ключом загрузки. Мастер Android Studio умеет создавать хранилище ключей и рекомендует срок действия не меньше 25 лет.
Чтобы подписывать из командной строки или в CI, храните учётные данные в файле keystore.properties вне системы контроля версий и читайте его в app/build.gradle.kts:
storePassword=myStorePassword
keyPassword=myKeyPassword
keyAlias=upload
storeFile=/path/to/upload-keystore.jksimport java.io.FileInputStream
import java.util.Properties
val keystoreProperties = Properties().apply {
load(FileInputStream(rootProject.file("keystore.properties")))
}
android {
signingConfigs {
create("release") {
keyAlias = keystoreProperties["keyAlias"] as String
keyPassword = keystoreProperties["keyPassword"] as String
storeFile = file(keystoreProperties["storeFile"] as String)
storePassword = keystoreProperties["storePassword"] as String
}
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
signingConfig = signingConfigs.getByName("release")
}
}
}Сделайте резервную копию хранилища и обоих паролей. Если ключ загрузки потерян или утёк, создайте новый и запросите сброс ключа загрузки в Play Console; ключ подписи приложения остаётся прежним.
Код версии и целевой уровень API
versionCode должен быть больше, чем у любого загруженного бандла в любом треке; versionName видят пользователи. Оба значения находятся в defaultConfig, рядом с уровнями SDK:
android {
compileSdk = 36
defaultConfig {
applicationId = "com.yourcompany.app"
targetSdk = 36
versionCode = 2
versionName = "1.0.1"
}
}С 31 августа 2026 года новые приложения и обновления должны быть нацелены на Android 16 (уровень API 36). Повышение targetSdk включает новое поведение платформы. Приложения, нацеленные на Android 15 и выше, отображаются от края до края, а в Android 16 отключить это уже нельзя, поэтому до начала теста проверьте, что экраны Compose правильно обрабатывают window insets.
Ловушки Kotlin и Compose
- R8 удаляет то, что нужно рефлексии. С
isMinifyEnabled = trueмодели сериализации, классы Retrofit или Gson и некоторые схемы внедрения зависимостей могут ломаться только в release. Добавьте правила вproguard-rules.proи проверьте вариант release. - Сюрпризы режима от края до края. Контент под строкой состояния и панелью навигации закрывает кнопки. Используйте отступы
Scaffoldили модификаторыWindowInsetsна каждом экране, который увидят тестировщики. - Отлаживаемый release. Если в типе сборки release стоит
isDebuggable = true, Play Console отклонит бандл. - Секреты подписи в git. Пароли, записанные прямо в
build.gradle.kts, оказываются в репозитории. Храните их вkeystore.propertiesили в секретах CI. - Нативные библиотеки и страницы 16 КБ. Приложения только на Kotlin уже поддерживают страницы памяти 16 КБ, но код NDK и библиотеки с файлами
.soнужно пересобрать или обновить. Play Console предупреждает об этом, а с 1 февраля 2027 года обновления без такой поддержки нельзя будет выпустить. - Проверка только debug. Тестировщики получают вариант release. Перед каждой загрузкой запускайте его хотя бы на одной свежей версии Android.
Читаемые трассировки: сопоставление R8 и нативные символы
Тестировщики запускают только релизный вариант, поэтому их сбои приходят из оптимизированного R8 кода с переименованными классами и методами. Сборка записывает сопоставление, которое отменяет это, в app/build/outputs/mapping/release/mapping.txt, перезаписывает его при каждой сборке и также кладёт в .aab.
Доверьте деобфускацию Play Console
Начиная с Android Gradle plugin 4.1, Play Console берёт файл сопоставления из загруженного бандла. Сбои в разделе Мониторинг и улучшение → Android Vitals → Сбои и ANR тогда показывают настоящие имена классов и методов.
Храните копию для каждого выпуска
Архивируйте
mapping.txtс каждым загруженным кодом версии. Он понадобится для трассировок, которые тестировщики вставляют в отчёты, и для любых инструментов сбоев вне Google Play.Восстанавливайте трассировку вручную
Запустите
retraceиз набора command-line tools с файлом сопоставления и файлом трассировки. Последние версии Android Studio также автоматически восстанавливают трассировки в Logcat.
$ANDROID_HOME/cmdline-tools/latest/bin/retrace \
app/build/outputs/mapping/release/mapping.txt trace.txtИспользуете NDK? Задайте debugSymbolLevel в релизном типе сборки. SYMBOL_TABLE даёт имена функций в Play Console, FULL добавляет файлы и номера строк. В app bundle нативные символы включаются и загружаются автоматически.
android {
buildTypes {
release {
ndk {
debugSymbolLevel = "FULL" // or "SYMBOL_TABLE"
}
}
}
}Если R8 оставляет неожиданный код или удаляет код, нужный для рефлексии, -whyareyoukeeping показывает путь от сохранённого класса до точки входа, а configuration.txt рядом с сопоставлением перечисляет все объединённые правила.
Коротко о Play Console: от закрытого теста до продакшена
Когда бандл Kotlin / Jetpack Compose собран и подписан, всё остальное происходит в Play Console и одинаково для любого фреймворка. Здесь краткий чек-лист; каждое меню и экран описаны в полном руководстве по Play Console.
- Завершите настройку приложения на панели управления: политика конфиденциальности, доступ к приложению, реклама, возрастной рейтинг, целевая аудитория, безопасность данных и страница в Play Маркете.
- Создайте выпуск для закрытого теста в разделе Тестирование и выпуск → Тестирование → Закрытое тестирование: выберите страны тестировщиков, загрузите
.aabи отправьте на проверку. - Добавьте тестировщиков через Google Группу на вкладке Тестировщики и поделитесь ссылкой opt-in. Она заработает, когда у трека появится статус Опубликовано.
- Держите не менее 12 тестировщиков с opt-in 14 дней подряд. Внутреннее тестирование не засчитывается, а у того, кто вышел и вернулся, отсчёт 14 дней начинается заново.
- Выпустите хотя бы одно обновление во время теста и запишите, что нашли тестировщики и что вы изменили.
- Подайте заявку на доступ к продакшену с панели управления и ответьте на три раздела о тесте, приложении и готовности. Решение принимает Google; никто не может гарантировать одобрение.
Учитывайте выбывших: наберите больше 12 тестировщиков, чтобы уход одного человека не сдвинул ваши сроки. Все шаги в Play Console.
Полное руководство по Play Console
Закрытый трек, Google Группа и ссылка opt-in, правило 12 тестировщиков / 14 дней и заявка на продакшен, шаг за шагом на одной странице.
Тестируйте именно тот бандл и выпускайте обновления
Увеличьте versionCode, пересоберите бандл (Gradle или мастер Android Studio) и загрузите его в тот же закрытый трек.
./gradlew bundleReleaseЧтобы установить бандл, который вы собираетесь загрузить, сгенерируйте из него APK для конкретного устройства с помощью bundletool, подписав ключом загрузки. Это ближе всего к тому, что доставляет Google Play, включая разделение по плотности экрана, языку и ABI:
bundletool build-apks --connected-device \
--bundle=app/build/outputs/bundle/release/app-release.aab --output=app.apks \
--ks=/path/to/upload-keystore.jks --ks-key-alias=upload
bundletool install-apks --apks=app.apksДля быстрых проверок вашей командой внутренний обмен приложениями в Play Console принимает любой код версии и даёт ссылку на скачивание для 100 человек максимум. Такие загрузки не могут входить в тестовый трек и не заменяют закрытый тест: ваши 12 тестировщиков всегда устанавливают приложение из закрытого трека.
Частые вопросы
Нужно ли загружать mapping.txt самому?
Не для app bundle, собранных с Android Gradle plugin 4.1 или новее: Play Console берёт его из .aab. Для APK нужна ручная загрузка, а инструментам сбоев вне Google Play нужна своя копия, так что архивируйте файл в любом случае.
Обязательна ли минификация?
Нет. isMinifyEnabled = true необязателен: он сжимает и обфусцирует код, и это же самая частая причина, по которой релизная сборка падает, а отладочная работает. Если включаете его, тестируйте релизный вариант перед каждой загрузкой.
Нужно ли что-то делать в Kotlin-приложении для страниц памяти 16 КБ?
Приложения только на Kotlin или Java уже поддерживают страницы 16 КБ. Если есть код NDK или библиотеки с файлами .so, используйте Android Gradle plugin 8.5.1 или новее и NDK r28 или новее, обновите эти библиотеки и протестируйте на образе эмулятора со страницами 16 КБ.
Стоит ли сначала провести внутреннее тестирование?
Можно. Внутреннее тестирование быстро настраивается и подходит для smoke-теста с командой, но не засчитывается в правило 12 тестировщиков, так что не позволяйте ему задерживать закрытый тест.
Источники
Технические детали сверены с официальной документацией ниже. Меню и значения по умолчанию меняются от версии к версии; если сомневаетесь, ориентируйтесь на официальную страницу.
- Android Developers: Sign your app
- Android Developers: Target API level requirements
- Android Developers: Support 16 KB page sizes
- Android Developers: Shrink, obfuscate, and optimize your app
- Android Developers: Troubleshoot app optimization (mapping.txt, retrace)
- Android Developers: Include native debug symbols
- Android Developers: bundletool
- Play Console Help: Internal app sharing
- Play Console Help: App testing requirements for new personal developer accounts
- Play Console Help: Set up an open, closed, or internal test
- Play Console Help: Deobfuscate or symbolicate crash stack traces
Впервые слышите о правиле 12 тестировщиков?
Общее руководство объясняет требование Google, как день за днём проходит кампания TestBunny и что мы можем и не можем гарантировать.
Читать общее руководство