Публикация Android-приложения
От сборки к публикации
Публикация в Store - отдельный контур работ
Когда проект собран в конфигурации release, остаётся два обязательных шага: подписать артефакт (APK или AAB) собственным ключом и выбрать канал распространения. Теория форматов пакетов, Play App Signing и CI/CD описана в статье Сборка и развёртывание мобильных приложений. Здесь — практическое руководство: создание keystore, настройка Gradle, сравнение магазинов и раздача APK с сайта.
Типичная ошибка новичка: загрузить в магазин или на сайт файл, подписанный отладочным ключом (debug.keystore). Такой ключ одинаков у всех разработчиков Android Studio, не привязан к вам лично и не подходит для продакшена. Google Play отклоняет такие сборки; RuStore и ручная установка формально допускают APK, но обновления «поверх» другой подписи невозможны — пользователю придётся удалить старую версию.
Отладочная и релизная подпись
| Параметр | Debug | Release |
|---|---|---|
| Файл ключей | ~/.android/debug.keystore (создаётся автоматически) | Ваш .jks / .keystore, созданный вручную |
| Пароль по умолчанию | android | Задаёте вы |
| Alias | androiddebugkey | Например, my-key-alias |
| Назначение | Запуск с IDE, USB-отладка | Магазины, сайт, корпоративная раздача |
| Обновления в магазине | Нельзя использовать для публикации | Один ключ на всё время жизни пакета (applicationId) |
Правило: для любой сборки, которую увидят пользователи вне вашей машины, нужен release keystore. Потеря файла и пароля означает, что вы не сможете выпускать обновления того же приложения в магазине — только новый пакет с другим applicationId (фактически новое приложение).
Если приложение уже опубликовано с debug-ключом, сменить подпись на release для тех же установок нельзя. Решения: не публиковали в прод — начать с release; уже в проде с debug — новый applicationId и новый ключ (потеря установок) или обращение в поддержку магазина (исключение, редко).
Создание release keystore
Keystore — файл (.jks или .keystore) с закрытым ключом и сертификатом. Храните копию в надёжном месте (менеджер паролей, зашифрованный архив), не коммитьте в Git.
Способ 1 — командная строка (keytool)
В каталоге проекта Android (или в любом месте, указав полный путь к файлу) выполните:
keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.jks -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
На Windows в PowerShell команда та же; keytool входит в JDK (часто: "%JAVA_HOME%\bin\keytool").
Параметры:
-keystore— имя создаваемого файла;-alias— имя ключа внутри хранилища (понадобится в Gradle);-validity— срок в днях (10000≈ 27 лет);- при запросе CN, организации и т.д. можно указать реальные или условные данные — они попадут в сертификат.
Задайте два пароля: на хранилище и на ключ (часто совпадают). Запомните alias.
Способ 2 — Android Studio
Build → Generate Signed Bundle / APK → Android App Bundle (или APK) → Next → Create new... — укажите путь, пароли, alias и срок действия. Studio создаст keystore и может сразу собрать подписанный артефакт.
Настройка Gradle
Пароли и путь к keystore не должны лежать в открытом виде в build.gradle, если репозиторий публичный. Стандартный вариант — local.properties (уже в .gitignore у типового Android-проекта) или переменные окружения CI.
Пример local.properties (файл в корне проекта, рядом с settings.gradle):
RELEASE_STORE_FILE=../keystore/my-release-key.jks
RELEASE_STORE_PASSWORD=ваш_пароль_хранилища
RELEASE_KEY_ALIAS=my-key-alias
RELEASE_KEY_PASSWORD=ваш_пароль_ключа
Путь RELEASE_STORE_FILE — относительно модуля app или абсолютный.
Groovy (app/build.gradle)
def keystorePropertiesFile = rootProject.file("local.properties")
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
signingConfigs {
release {
storeFile file(keystoreProperties['RELEASE_STORE_FILE'])
storePassword keystoreProperties['RELEASE_STORE_PASSWORD']
keyAlias keystoreProperties['RELEASE_KEY_ALIAS']
keyPassword keystoreProperties['RELEASE_KEY_PASSWORD']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
Kotlin DSL (app/build.gradle.kts)
val keystorePropertiesFile = rootProject.file("local.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(keystorePropertiesFile.inputStream())
}
android {
signingConfigs {
create("release") {
storeFile = file(keystoreProperties["RELEASE_STORE_FILE"] as String)
storePassword = keystoreProperties["RELEASE_STORE_PASSWORD"] as String
keyAlias = keystoreProperties["RELEASE_KEY_ALIAS"] as String
keyPassword = keystoreProperties["RELEASE_KEY_PASSWORD"] as String
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}
В CI вместо local.properties передают те же имена через секреты: RELEASE_STORE_FILE, пароли — как зашифрованные переменные пайплайна.
Сборка подписанного APK и AAB
Из корня проекта Android:
# Linux / macOS
./gradlew assembleRelease
./gradlew bundleRelease
# Windows
gradlew.bat assembleRelease
gradlew.bat bundleRelease
Результаты (пути могут отличаться по версии AGP):
- APK:
app/build/outputs/apk/release/app-release.apk - AAB:
app/build/outputs/bundle/release/app-release.aab
Перед загрузкой увеличивайте в build.gradle модуля app:
versionCode— целое, строго больше предыдущей публикации (иначеINSTALL_FAILED_VERSION_DOWNGRADE);versionName— строка для людей (1.0.1).
Для Google Play предпочтителен AAB; для RuStore, сайта и прямой установки часто достаточно одного универсального APK.
Проверка подписи
Убедитесь, что подпись не отладочная:
apksigner verify --verbose app/build/outputs/apk/release/app-release.apk
Требуется Android SDK Build-Tools (apksigner в build-tools/<version>/).
Сравнить отпечаток сертификата release и debug:
keytool -list -v -keystore my-release-key.jks -alias my-key-alias
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android
SHA-256 в выводе должны различаться. Тот же SHA-256 можно опубликовать на странице загрузки на сайте — пользователь сверит подпись установленного APK через настройки Android → «О приложении» → сертификаты.
Для AAB: Bundle Explorer или загрузка в Play Console / внутренний трек — в карточке виден сертификат upload key.
Куда публиковать — сравнение каналов
| Критерий | Сайт (прямой APK) | RuStore | Google Play | App Store (iOS) |
|---|---|---|---|---|
| Вход для разработчика | 0 ₽ | 0 ₽ | ~$25 (единоразово) | ~$99/год |
| Оплата из РФ | Не нужна | Обычно без проблем | Часто сложно (карта, валюта) | Часто сложно |
| Формат | APK (реже AAB вручную) | APK, AAB | AAB (APK для старых треков) | IPA |
| Автообновления | Нет | Да (магазин) | Да | Да |
| Доверие пользователя | Среднее | Высокое в РФ | Высокое глобально | Очень высокое |
| Модерация | Нет | Да | Да | Строгая |
| Санкции / гео | Нет привязки | Ориентир на РФ | Ограничения для платежей и аккаунта | Ограничения для платежей |
Практичная стратегия без бюджета на зарубежные магазины: release-сборка → RuStore (основной магазин для аудитории в России) + страница на сайте с APK и контрольной суммой (резервная ссылка, бета, корпоративные пользователи). Google Play — когда появится возможность оплатить аккаунт и нужна глобальная витрина.
Пользователи в России скачивают из Google Play; ограничение для разработчика — регистрация и $25, а не «закрытый магазин» для страны.
RuStore
Консоль разработчика RuStore — регистрация бесплатна, для физлица обычно нужны данные паспорта РФ (для юрлица — ИНН).
Что загружать: готовый APK или AAB, подписанный вашим release-ключом. Исходный код и структура проекта не передаются.
Модерация проверяет:
- манифест (разрешения, компоненты,
applicationId); - поведение приложения (запуск, заявленный функционал);
- соответствие описанию и законодательству РФ;
- автоматически — вредоносный код.
Что не видят модераторы: ваши .kt / .java файлы и папки проекта. Внутри APK теоретически возможен реверс-инжиниринг байт-кода (как для любого APK в открытом доступе). Поэтому в release включайте R8 (minifyEnabled true) и не храните API-ключи и пароли в коде — см. обфускацию в статье о сборке.
Риски: потеря доступа к аккаунту разработчика; отказ из-за лишних разрешений или несоответствия описанию; извлечение секретов из APK при слабой обфускации. Включите 2FA в кабинете, если доступна.
Раздача APK с сайта
Подходит для проектов без магазина или как дополнение к RuStore.
Структура на сервере (пример):
/downloads/
my-app-1.0.0.apk
my-app-1.0.0.sha256.txt
install-guide.md
Контрольная сумма (Windows PowerShell):
Get-FileHash -Algorithm SHA256 .\my-app-1.0.0.apk
Сохраните строку хеша в .sha256.txt рядом с файлом. На Linux/macOS: sha256sum my-app-1.0.0.apk.
Страница для пользователя должна содержать:
- Ссылку на APK и хеш SHA-256.
- Минимальную версию Android (
minSdkVersionиз манифеста). - Шаги: скачать → при необходимости проверить хеш → разрешить установку из этого источника (браузер или «Файлы») → установить.
- Краткий дисклеймер «как есть» и ссылку на политику конфиденциальности, если приложение что-то собирает.
Ограничения: нет push об обновлении от магазина; Play Protect может предупредить о «неизвестном» источнике — это нормально для sideload; один универсальный APK проще для пользователя, чем несколько файлов по архитектурам.
Google Play (кратко)
Нужен аккаунт разработчика и оплата регистрации. Загружается AAB, подписанный upload key; при включённом Play App Signing Google хранит app signing key — подробности в 112.md.
Для новых приложений в консоли заполняют карточку, политику конфиденциальности, скриншоты и проходят модерацию. Обновления только с тем же upload key (или по процедуре сброса ключа в консоли).
iOS и альтернатива без App Store
Нативное приложение для iPhone без Apple Developer Program (~$99/год) в App Store не опубликовать. Установка .ipa вне магазина для обычного пользователя без jailbreak практически недоступна.
Варианты без оплаты Apple:
- PWA — веб-приложение с манифестом и Service Worker; установка через Safari «На экран Домой». Подробнее: PWA в мобильных приложениях.
- Отложить iOS и сосредоточиться на Android + веб.
TestFlight и Ad Hoc тоже требуют платный аккаунт и ограничены по устройствам.
Чек-лист перед публикацией
- Сборка
release, неdebug. - Подпись через свой keystore, не
debug.keystore. -
versionCodeувеличен относительно предыдущей публикации. -
minifyEnabled trueи правила ProGuard/R8 для кода с reflection. - Секреты (API keys, пароли БД) не в исходниках APK.
- Резервная копия
.jksи паролей в безопасном хранилище. - Протестирована установка «с нуля» на чистом устройстве.
- Для сайта: опубликован SHA-256; для магазина: скриншоты и политика конфиденциальности.
Частые ошибки
| Симптом | Причина |
|---|---|
| Play отклонил APK | Debug-подпись или заниженный versionCode |
| «App not installed» на телефоне | Конфликт подписи с уже установленной версией |
| R8 сломал reflection | Нет keep-правил в proguard-rules.pro |
| Обновление невозможно | Потерян keystore — только новый applicationId |
Что попробовать
bundletool— проверьте AAB локально перед загрузкой.- Internal testing track в Play Console — тест без публичного релиза.
- RuStore + Google Play — один и тот же release-ключ на оба канала.
Частые ошибки
| Симптом | Причина |
|---|---|
| Play отклонил APK | Debug-подпись или заниженный versionCode |
| «App not installed» на телефоне | Конфликт подписи с уже установленной версией |
| R8 сломал reflection | Нет keep-правил в proguard-rules.pro |
| Обновление невозможно | Потерян keystore — только новый applicationId |
Что попробовать
bundletool— проверьте AAB локально перед загрузкой.- Internal testing track в Play Console — тест без публичного релиза.
- RuStore + Google Play — один и тот же release-ключ на оба канала.
Связанные материалы
- Сборка и развёртывание мобильных приложений — форматы APK/AAB, Play App Signing, R8, CI/CD.
- Мобильные приложения (обзор) — экосистемы iOS и Android, монетизация в магазинах.
- PWA в мобильных приложениях — кроссплатформенность без App Store.
- Kotlin, Java, React Native, Expo, MAUI — стеки с отсылкой к этой статье в разделе публикации.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Программы для смартфонов. Особенности мобильной разработки. Компоненты UI на Android - иерархия View, разметка экранов и организация взаимодействия пользователя с приложением. Сборка — не техническая рутина, а акт проектирования доверия. Каждый APK и IPA — это договор между разработчиком и пользователем, закодированный в битах. Отладка по USB представляет собой механизм взаимодействия между компьютером разработчика и устройством на базе Android. Суперапп представляет собой мобильное приложение, объединяющее множество самостоятельных сервисов в единую платформу. Пошаговый старт: Первая программа на React Native · Expo · Первая программа на Expo. Старт React Native — Expo или CLI, компоненты View/Text, состояние и запуск на эмуляторе. Набор инструментов и сервисов на базе React Native. Expo — create-expo-app, Expo Go, hot reload, EAS и переход к development build. Кроссплатформенная разработка на .NET. Flutter - платформа, а Dart - язык программирования. Язык программирования, стандарт для разработки под Android.Мобильные приложения
Компоненты пользовательского интерфейса на Android
Сборка и развёртывание мобильных приложений
Отладка по USB на Android
Супераппы
React Native
Первая программа на React Native
Expo
Первая программа на Expo
MAUI
Dart
Kotlin в мобильных приложениях