Тема
Выбор Android-стека
Стек выбирается по продукту и уже существующему коду. Codex не должен начинать реализацию, пока не определены основной пользовательский сценарий, источники данных, offline-требования, device API, form factors и граница публикации.
Быстрое решение
| Исходная ситуация | Предпочтительный путь | Когда выбрать другое |
|---|---|---|
| Новый Android-first продукт | Kotlin, Jetpack Compose, Gradle Kotlin DSL | Нужен уже выбранный cross-platform stack |
| Готовый web/PWA с локальным build | Capacitor 8 с bundled assets | Web runtime не удовлетворяет UX/performance/device API |
| Клиент к REST/GraphQL/WebSocket API | Native Compose + data/repository layer | Существует зрелый web/cross-platform клиент |
| Простое отображение собственного сайта | TWA только при осознанной зависимости от сети | Нужен offline или нативные функции |
| Тяжёлая 2D/3D-игра | Godot/libGDX/другой согласованный engine | Механика уже качественно работает как web game |
| Wear OS, TV, Auto, XR | Native platform-specific проект | Только если framework официально закрывает form factor |
Если проект уже существует, сохраняйте его stack. Миграция допустима только при измеримой проблеме: неподдерживаемая платформа, безопасность, lifecycle, производительность или стоимость развития.
Ветка A: Kotlin и Jetpack Compose
Это default для нового приложения, ориентированного прежде всего на Android. Начинайте с одного app module; делите на Gradle modules только при реальном выигрыше в изоляции, времени сборки или ownership.
text
UI (Compose screen + immutable UiState)
↓ events ↑ state
ViewModel / state holder
↓
Repository (единая граница данных)
├── local source: Room/DataStore/files
└── remote/device source: API, Bluetooth, location и т.п.- Single-activity и Compose navigation для многоэкранного phone/tablet app.
- Однонаправленный поток: state вниз, события вверх.
- ViewModel не хранит
Activity, View или долгоживущийContext. - Coroutines/Flow и lifecycle-aware collection.
- Domain/use-case layer только при повторяемой или сложной бизнес-логике.
- DataStore для небольших настроек, Room для структурированных данных.
- WorkManager для гарантированной отложенной работы, не бесконечный service.
- Adaptive layouts и сохранение состояния при resize/rotation/process death.
Официальная основа: Guide to app architecture и Architecture recommendations.
Ветка B: API-backed приложение
Это data/runtime профиль поверх native или согласованного cross-platform stack.
- Контракт API фиксируется schema/spec и проверяется contract tests.
- UI имеет наблюдаемые
loading,content,empty,error,offlineиauth-requiredstates. - Репозиторий определяет source of truth; network-вызовы не размазываются по UI.
- Таймауты, отмена, retry и идемпотентность задаются по операции.
- Backend secrets никогда не помещаются в APK. Пользовательские credentials и tokens хранятся по Android security guidance и удаляются при logout/delete.
- При offline-first чтение доступно из локального источника, а очередь записи имеет понятную стратегию конфликтов и синхронизации.
- TLS обязателен; Network Security Config не ослабляется для production.
Не обещайте offline, если без сервера основной сценарий невозможен. Вместо скрытого зависания показывайте понятное состояние и восстановление.
Ветка C: Capacitor
Используйте для существующего web/PWA, когда production bundle можно встроить в приложение. Native shell не должен загружать dev server или remote исполняемый код.
text
src/ или web/ source of truth
dist/ воспроизводимый production bundle
capacitor.config.* appId, appName, webDir
android/ Gradle Wrapper и native integration
docs/play/ policy/release evidence- Версии Capacitor core/CLI/Android совпадают.
dist/и Android assets генерируются, а не редактируются вручную.- Для offline продукта все критичные assets локальны.
- Каждый plugin проходит permissions, SDK и Data Safety review.
- WebView/TWA чужого сайта без прав и самостоятельной ценности недопустимы.
Проверенный пример этой ветки: arcade-android/.
Ветка D: device и background capabilities
Камера, микрофон, location, Bluetooth, notifications, Accessibility, VpnService, exact alarms, foreground services и broad storage access меняют не только код, но и Google Play review.
До добавления capability зафиксируйте:
- user-facing функцию, которой она необходима;
- минимальный API/permission и вариант без permission;
- момент contextual request и поведение при отказе;
- сбор/передачу/retention данных и сторонние SDK;
- нужную Play declaration, disclosure и review evidence.
Предпочитайте системные scoped API: Photo Picker вместо broad media/storage access, system document picker вместо MANAGE_EXTERNAL_STORAGE, WorkManager вместо постоянной фоновой службы, когда это закрывает сценарий.
Ветка E: игры и media
- Canvas/WebGL игра с существующим web-кодом может остаться в Capacitor.
- Native casual game может использовать Compose/Canvas, если performance подтверждён профилированием.
- Для тяжёлой 2D/3D-графики выбирайте engine отдельно и проверяйте native ABI, 64-bit и 16 KB page-size compatibility.
- Background playback требует корректной media session/foreground service модели и Play declarations.
Не выбирайте game engine или тяжёлый SDK «на будущее»: сначала нужен реальный технический сценарий.
Неизменяемые решения до первой публикации
- package/application ID;
- владелец app record и signing model;
- тип продукта и заявленная аудитория;
- фактические data/ads/account capabilities;
- supported form factors.
versionCode всегда растёт. Target/compile SDK, зависимости и Play policy проверяются заново перед релизом, а не копируются из старого проекта.
Риск repetitive content
Google Play оценивает самостоятельную ценность приложения. Серия wrappers, справочников или игр, различающихся только цветом, названием, контентным файлом или иконкой, создаёт риск spam/repetitive content. Безопаснее один качественный продукт с каталогом функций либо действительно разные приложения с разными задачами, UX и store listing.