# 🏗️ Сборка AAB/APK из России — Полное руководство > **Дата создания:** 2026-02-28 > **Проблема:** Java TLS заблокирован российским DPI → Gradle не может скачать зависимости > **Решение:** Maven proxy на прод-сервере + SSH-туннель + обход SDK auto-download > **Время сборки:** ~1.5 мин (AAB), ~46 сек (APK после AAB) > > **📖 См. также:** [SETUP_AND_BUILD_GUIDE.md](./SETUP_AND_BUILD_GUIDE.md) — общее руководство по установке и сборке (для работы не из России) --- ## 📋 Содержание 1. [Суть проблемы](#-суть-проблемы) 2. [Предварительные требования](#-предварительные-требования) 3. [Шаг 1: Maven proxy на прод-сервере](#-шаг-1-maven-proxy-на-прод-сервере) 4. [Шаг 2: SSH-туннель](#-шаг-2-ssh-туннель) 5. [Шаг 3: Сборка AAB](#-шаг-3-сборка-aab) 6. [Шаг 4: Сборка APK для эмулятора](#-шаг-4-сборка-apk-для-эмулятора) 7. [Шаг 5: Установка в эмулятор](#-шаг-5-установка-в-эмулятор) 8. [Быстрый скрипт «всё одной командой»](#-быстрый-скрипт-всё-одной-командой) 9. [DOs & DON'Ts](#-dos--donts) 10. [Конфигурация Gradle (что изменено и почему)](#-конфигурация-gradle-что-изменено-и-почему) 11. [Troubleshooting](#-troubleshooting) 12. [Версионирование](#-версионирование) --- ## 🔍 Суть проблемы ### Почему Gradle не работает из России напрямую ``` Gradle → Java TLS → dl.google.com / repo1.maven.org ↑ DPI (Deep Packet Inspection) блокирует TLS handshake Java получает: "Remote host terminated the handshake" ``` **Ключевой факт:** `curl` работает нормально (macOS LibreSSL), а Java — нет (JSSE TLS implementation). DPI по-разному обрабатывает TLS Client Hello от разных реализаций. ### Решение: Maven proxy ``` Gradle → HTTP (127.0.0.1:8765) → SSH-туннель → Прод-сервер (python proxy) ↓ HTTPS → dl.google.com HTTPS → repo1.maven.org HTTPS → plugins.gradle.org ``` Java работает по **HTTP** (без TLS) до localhost. Прод-сервер в Digital Ocean скачивает по **HTTPS** без DPI. --- ## ✅ Предварительные требования > **📖 Перед началом:** Убедитесь, что выполнены базовые требования из [SETUP_AND_BUILD_GUIDE.md](./SETUP_AND_BUILD_GUIDE.md): > - Java OpenJDK 21+ установлен > - Android SDK установлен (через Android Studio GUI) > - Build Tools установлены > - Эмулятор настроен (см. [EMULATOR_STARTUP_GUIDE.md](./EMULATOR_STARTUP_GUIDE.md)) ### Локальная машина (macOS) | Компонент | Версия | Путь | |-----------|--------|------| | Java (OpenJDK) | 21.0.9 | `/opt/homebrew/opt/openjdk@21` | | Android SDK | API 34-36 | `$HOME/Library/Android/sdk` | | Build Tools | 35.0.1 | `$HOME/Library/Android/sdk/build-tools/35.0.1` | | Gradle Wrapper | 8.11.1 | `frontend/android/gradle/wrapper/` | | AGP | 8.7.2 | `frontend/android/build.gradle` | | Capacitor | 7.4.x | `frontend/package.json` | ### Прод-сервер | Компонент | Значение | |-----------|----------| | SSH хост | `hunab-prod` (209.38.32.21) | | Python | 3.12+ (предустановлен) | | Порт proxy | 8765 (localhost) | ### Проверка готовности ```bash # Java /opt/homebrew/opt/openjdk@21/bin/java -version # → openjdk version "21.0.9" # Android SDK ls $HOME/Library/Android/sdk/platforms/ # → android-34 android-35 android-36 # Build Tools ls $HOME/Library/Android/sdk/build-tools/ # → 35.0.1 36.1.0 (34.0.0 и 35.0.0 УДАЛЕНЫ — были пустые!) # SSH к проду ssh hunab-prod "echo OK" # → OK ``` --- ## 🔧 Шаг 1: Maven proxy на прод-сервере ### 1.1 Скопировать скрипт прокси на прод Создать файл `/tmp/maven-proxy.py` локально: ```bash cat > /tmp/maven-proxy.py << 'PYEOF' #!/usr/bin/env python3 """Многопоточный Maven reverse proxy для Gradle. Обходит Java TLS/DPI блокировку при сборке Android из РФ. Поддерживает GET и HEAD запросы (Gradle использует оба). """ import http.server, socketserver, urllib.request, ssl, sys REPOS = { '/google/': 'https://dl.google.com/dl/android/maven2/', '/central/': 'https://repo1.maven.org/maven2/', '/gradle/': 'https://plugins.gradle.org/m2/', } class H(http.server.BaseHTTPRequestHandler): def _p(self, m='GET'): for pfx, base in REPOS.items(): if self.path.startswith(pfx): url = base + self.path[len(pfx):] try: r = urllib.request.urlopen( urllib.request.Request(url, headers={'User-Agent':'Gradle'}, method=m), timeout=300, context=ssl.create_default_context() ) d = r.read() if m=='GET' else b'' self.send_response(200) self.send_header('Content-Type', r.headers.get('Content-Type','application/octet-stream')) self.send_header('Content-Length', r.headers.get('Content-Length',str(len(d)))) self.end_headers() if m=='GET': self.wfile.write(d) except urllib.error.HTTPError as e: self.send_response(e.code); self.end_headers() except Exception as e: sys.stderr.write(f"ERR {m} {url}: {e}\n"); sys.stderr.flush() self.send_response(502); self.end_headers() return self.send_response(404); self.end_headers() def do_GET(self): self._p('GET') def do_HEAD(self): self._p('HEAD') def log_message(self, fmt, *a): sys.stderr.write(f"{a[0]}\n"); sys.stderr.flush() class S(socketserver.ThreadingMixIn, http.server.HTTPServer): daemon_threads = True; allow_reuse_address = True if __name__ == '__main__': print("Maven proxy v2 on :8765 (threaded+logging)") sys.stdout.flush() S(('127.0.0.1',8765),H).serve_forever() PYEOF ``` Скопировать на прод: ```bash scp /tmp/maven-proxy.py hunab-prod:/tmp/maven-proxy.py ``` ### 1.2 Запустить прокси на проде ```bash # Убить предыдущий экземпляр (НЕЛЬЗЯ использовать pkill -f maven-proxy — убьёт SSH сессию!) ssh hunab-prod "ps aux | grep maven-proxy | grep python | grep -v grep | awk '{print \$2}' | xargs -r kill" sleep 1 # Запустить ssh hunab-prod "nohup python3 /tmp/maven-proxy.py > /tmp/maven-proxy.log 2>&1 & echo PID=\$!" ``` ### 1.3 Проверить прокси на проде ```bash ssh hunab-prod "curl -s -I http://127.0.0.1:8765/google/com/android/tools/build/gradle/8.7.2/gradle-8.7.2.pom | head -2" # Ожидаемый ответ: # HTTP/1.0 200 OK # Server: BaseHTTP/0.6 Python/3.12.7 ``` --- ## 🔧 Шаг 2: SSH-туннель ### 2.1 Создать туннель ```bash # Убить старые туннели pkill -f "ssh.*-L.*8765" 2>/dev/null # Новый туннель (фоновый режим) ssh -f -N -L 8765:127.0.0.1:8765 hunab-prod ``` ### 2.2 Проверить туннель локально ```bash curl -s -I http://127.0.0.1:8765/google/com/android/tools/build/gradle/8.7.2/gradle-8.7.2.pom | head -2 # Ожидаемый ответ: # HTTP/1.0 200 OK # Server: BaseHTTP/0.6 Python/3.12.7 ``` **⚠️ Если ответ пустой или "Connection refused"** — прокси на проде не запущен или туннель не работает. Повторите шаги 1.2 и 2.1. --- ## 🔧 Шаг 3: Сборка AAB ### 3.1 Установка переменных окружения ```bash export JAVA_HOME=/opt/homebrew/opt/openjdk@21 export PATH="$JAVA_HOME/bin:$PATH" export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/platform-tools ``` ### 3.2 Сборка фронтенда (если не собран) ```bash cd /Users/eternal/code/hunabapp-dev/frontend pnpm build ``` ### 3.3 Синхронизация Capacitor (если не сделано) ```bash cd /Users/eternal/code/hunabapp-dev/frontend npx cap sync android ``` ### 3.4 Сборка AAB ```bash cd /Users/eternal/code/hunabapp-dev/frontend/android ./gradlew clean bundleRelease --no-daemon --console=plain ``` **Ожидаемое время:** ~1 мин 20 сек ### 3.5 Результат ```bash ls -lh ./app/build/outputs/bundle/release/app-release.aab # → 37M app-release.aab ``` ### 3.6 Копирование в temp/ ```bash VERSION_NAME=$(grep 'versionName' ./app/build.gradle | grep -oE '"[^"]*"' | tr -d '"') VERSION_CODE=$(grep 'versionCode' ./app/build.gradle | grep -oE '[0-9]+') mkdir -p /Users/eternal/code/hunabapp-dev/temp/android cp ./app/build/outputs/bundle/release/app-release.aab \ /Users/eternal/code/hunabapp-dev/temp/android/hunab-app-v${VERSION_NAME}-v${VERSION_CODE}-release.aab echo "📦 AAB: temp/android/hunab-app-v${VERSION_NAME}-v${VERSION_CODE}-release.aab" ``` --- ## 🔧 Шаг 4: Сборка APK для эмулятора > **AAB нельзя установить в эмулятор напрямую** — нужен APK. ```bash cd /Users/eternal/code/hunabapp-dev/frontend/android ./gradlew assembleRelease --no-daemon --console=plain ``` **Ожидаемое время:** ~46 сек (после AAB сборки — кэш уже разогрет) Результат: ```bash cp ./app/build/outputs/apk/release/app-release.apk \ /Users/eternal/code/hunabapp-dev/temp/android/hunab-app-v${VERSION_NAME}-release.apk ``` --- ## 🔧 Шаг 5: Установка в эмулятор ### 5.1 Запуск эмулятора ```bash # Список доступных AVD $ANDROID_HOME/emulator/emulator -list-avds # → Pixel_5_API_35 # Запуск (в фоне) $ANDROID_HOME/emulator/emulator -avd Pixel_5_API_35 -no-snapshot-load -no-snapshot-save & # Ожидание загрузки (30-60 сек) adb wait-for-device adb shell getprop sys.boot_completed # → 1 (когда загружено) ``` ### 5.2 Установка APK ```bash adb install -r /Users/eternal/code/hunabapp-dev/temp/android/hunab-app-v${VERSION_NAME}-release.apk ``` ### 5.3 Запуск приложения ```bash adb shell am start -n com.hunab.app/.MainActivity ``` --- ## 🚀 Быстрый скрипт «всё одной командой» > **Предполагает:** прокси уже запущен и SSH-туннель активен (шаги 1-2). ```bash #!/bin/bash set -e # === Настройка === export JAVA_HOME=/opt/homebrew/opt/openjdk@21 export PATH="$JAVA_HOME/bin:$PATH" export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator PROJECT_ROOT="/Users/eternal/code/hunabapp-dev" # === Проверка прокси === echo "🔍 Проверяю Maven proxy..." if ! curl -s -I http://127.0.0.1:8765/google/com/android/tools/build/gradle/8.7.2/gradle-8.7.2.pom | grep -q "200 OK"; then echo "❌ Maven proxy не работает! Запустите шаги 1-2 из BUILD_AAB_FROM_RUSSIA_GUIDE.md" exit 1 fi echo "✅ Proxy OK" # === Сборка фронтенда === echo "🔨 Сборка фронтенда..." cd "$PROJECT_ROOT/frontend" pnpm build # === Capacitor sync === echo "🔄 Capacitor sync..." npx cap sync android # === Версия === cd android VERSION_NAME=$(grep 'versionName' ./app/build.gradle | grep -oE '"[^"]*"' | tr -d '"') VERSION_CODE=$(grep 'versionCode' ./app/build.gradle | grep -oE '[0-9]+') echo "📊 Version: $VERSION_NAME (code: $VERSION_CODE)" # === AAB === echo "📦 Сборка AAB..." ./gradlew clean bundleRelease --no-daemon --console=plain mkdir -p "$PROJECT_ROOT/temp/android" cp ./app/build/outputs/bundle/release/app-release.aab \ "$PROJECT_ROOT/temp/android/hunab-app-v${VERSION_NAME}-v${VERSION_CODE}-release.aab" echo "✅ AAB: temp/android/hunab-app-v${VERSION_NAME}-v${VERSION_CODE}-release.aab" # === APK (для эмулятора) === echo "📱 Сборка APK..." ./gradlew assembleRelease --no-daemon --console=plain cp ./app/build/outputs/apk/release/app-release.apk \ "$PROJECT_ROOT/temp/android/hunab-app-v${VERSION_NAME}-release.apk" # === Эмулятор === echo "📲 Установка в эмулятор..." if adb devices 2>/dev/null | grep -q "device$"; then adb install -r "$PROJECT_ROOT/temp/android/hunab-app-v${VERSION_NAME}-release.apk" adb shell am start -n com.hunab.app/.MainActivity echo "🎮 Приложение запущено!" else echo "⚠️ Эмулятор не запущен. Запустите вручную и повторите установку." fi ls -lh "$PROJECT_ROOT/temp/android/" echo "" echo "✅✅✅ ГОТОВО!" ``` --- ## 🚫 DOs & DON'Ts ### ✅ DO (ДЕЛАЙ) | # | Правило | Почему | |---|---------|--------| | 1 | **Используй Maven proxy через SSH-туннель** | Java TLS заблокирован DPI в РФ | | 2 | **ТОЛЬКО прокси repos в build.gradle** (без `google()`, `mavenCentral()`) | Прямые HTTPS repos зависают навсегда | | 3 | **`allowInsecureProtocol = true`** для proxy repos | Прокси работает по HTTP, Gradle 8+ блокирует HTTP по умолчанию | | 4 | **`android.builder.sdkDownload=false`** в gradle.properties | SDK auto-download зависает на TLS | | 5 | **`compileSdkVersion = 36`** в variables.gradle | android-36 — base SDK, корректно установлен | | 6 | **`buildToolsVersion "35.0.1"`** явно в app/build.gradle | 34.0.0 и 35.0.0 не установлены (пустые папки были удалены) | | 7 | **Global buildToolsVersion override** через `subprojects{}` в root build.gradle | Capacitor модули тоже требуют build tools | | 8 | **`android.suppressUnsupportedCompileSdk=36`** в gradle.properties | Убирает warning от AGP 8.7.2 | | 9 | **`-Djdk.tls.client.protocols=TLSv1.2`** в org.gradle.jvmargs | Частично помогает с DPI для прямых Java TLS | | 10 | **`IsBaseSdk=true`** в source.properties platforms | Gradle не находит extension SDK без манифеста | | 11 | **`ThreadingMixIn`** в Python proxy | Gradle делает десятки параллельных запросов | | 12 | **HEAD + GET** в proxy | Gradle использует HEAD для проверки существования артефактов | | 13 | **Фоновая сборка** при запуске из Cursor | `./gradlew` через Cursor tool таймаутится через ~2 мин | | 14 | **Убивай pkill через `ps aux | grep | awk | xargs kill`** | Безопасный способ | ### ❌ DON'T (НЕ ДЕЛАЙ) | # | Правило | Почему | |---|---------|--------| | 1 | **НЕ оставляй `google()` / `mavenCentral()` в repositories** | Gradle попробует их → зависнет на TLS handshake на НЕОПРЕДЕЛЁННОЕ время | | 2 | **НЕ используй `pkill -f maven-proxy`** через SSH | Паттерн совпадает с самой SSH командой → убивает SSH сессию (exit 255) | | 3 | **НЕ используй однопоточный Python HTTP server** | Gradle делает 10-50 параллельных запросов → очередь → таймаут | | 4 | **НЕ используй SOCKS proxy для Gradle** (`socksProxyHost`) | Java TLS через SOCKS тоже блокируется DPI | | 5 | **НЕ пытайся скачать Gradle cache на проде и скопировать** | Кэш привязан к хэшам и абсолютным путям — не переносим | | 6 | **НЕ устанавливай Android SDK через sdkmanager из РФ** | Тот же TLS блок. Устанавливай через Android Studio GUI (у студии свои настройки) | | 7 | **НЕ удаляй `android.builder.sdkDownload=false`** | Gradle будет пытаться скачать SDK манифесты → зависнет | | 8 | **НЕ используй `compileSdkVersion = 35`** | Установленный android-35 — extension SDK, Gradle без манифеста не может его найти | | 9 | **НЕ забывай `buildToolsVersion` в subprojects** | Capacitor-android и другие модули тоже требуют build tools | | 10 | **НЕ создавай APK для Google Play** | Google Play требует только AAB формат | | 11 | **НЕ оставляй пустые build-tools директории** | Gradle пытается их использовать → "Build Tools not found" | | 12 | **НЕ запускай Gradle через tool call Cursor напрямую** | Таймаут ~2 мин; запускай в фоне через `nohup ... &` | --- ## ⚙️ Конфигурация Gradle (что изменено и почему) ### `frontend/android/build.gradle` (корневой) ```groovy buildscript { repositories { // ТОЛЬКО прокси — прямые repos заблокированы DPI maven { url 'http://127.0.0.1:8765/google/'; allowInsecureProtocol = true } maven { url 'http://127.0.0.1:8765/central/'; allowInsecureProtocol = true } maven { url 'http://127.0.0.1:8765/gradle/'; allowInsecureProtocol = true } } dependencies { classpath 'com.android.tools.build:gradle:8.7.2' classpath 'com.google.gms:google-services:4.4.2' } } allprojects { repositories { // ТОЛЬКО прокси maven { url 'http://127.0.0.1:8765/google/'; allowInsecureProtocol = true } maven { url 'http://127.0.0.1:8765/central/'; allowInsecureProtocol = true } maven { url 'http://127.0.0.1:8765/gradle/'; allowInsecureProtocol = true } } } // Глобальный override buildToolsVersion для ВСЕХ модулей subprojects { afterEvaluate { project -> if (project.hasProperty('android')) { project.android.buildToolsVersion = "35.0.1" } } } ``` **Почему:** - `allowInsecureProtocol = true` — Gradle 8+ блокирует HTTP repos по умолчанию - Три прокси: Google Maven, Maven Central, Gradle Plugin Portal - `subprojects { afterEvaluate }` — Capacitor модули не указывают buildToolsVersion явно, AGP 8.7.2 по умолчанию ищет 34.0.0 (не установлен) ### `frontend/android/gradle.properties` ```properties org.gradle.jvmargs=-Xmx1536m -Djdk.tls.client.protocols=TLSv1.2 android.useAndroidX=true android.builder.sdkDownload=false android.suppressUnsupportedCompileSdk=36 ``` **Почему:** - `-Djdk.tls.client.protocols=TLSv1.2` — принудительный TLS 1.2 (частично обходит DPI) - `sdkDownload=false` — блокирует авто-загрузку SDK (зависает на TLS) - `suppressUnsupportedCompileSdk=36` — AGP 8.7.2 не знает о SDK 36, подавляем warning ### `frontend/android/variables.gradle` ```groovy ext { compileSdkVersion = 36 // Было 35! android-35 — extension SDK, не находится без манифеста targetSdkVersion = 35 // Оставляем 35 для совместимости с Google Play // ... } ``` **Почему:** - `android-35` установлен как extension SDK (path: `platforms;android-35-ext15`) — Gradle без сетевого манифеста не может его распознать как `android-35` - `android-36` установлен как base SDK (path: `platforms;android-36`, `IsBaseSdk=true`) — работает - `targetSdkVersion` остаётся 35 — это то, что Google Play учитывает ### `frontend/android/app/build.gradle` ```groovy android { compileSdk rootProject.ext.compileSdkVersion buildToolsVersion "35.0.1" // Добавлено явно // ... } ``` ### SDK Platform Patches **`$HOME/Library/Android/sdk/platforms/android-35/source.properties`:** ```properties AndroidVersion.IsBaseSdk=true # Было false — Gradle не находил SDK без манифеста ``` **`$HOME/Library/Android/sdk/platforms/android-35/package.xml`:** ```xml ``` > ⚠️ Аналогичные изменения для android-34 --- ## 🔧 Troubleshooting ### Проблема: «Still waiting for package manifests to be fetched remotely» **Причина:** `android.builder.sdkDownload=true` (или не задан) → Gradle пытается скачать манифесты по HTTPS → DPI блокирует. **Решение:** ```properties # gradle.properties android.builder.sdkDownload=false ``` ### Проблема: «Failed to find target with hash string 'android-35'» **Причина:** Установленный SDK — extension SDK (`IsBaseSdk=false`, path `android-35-ext15`), а Gradle ищет base SDK `android-35`. **Решение варианты:** 1. Использовать `compileSdkVersion = 36` (android-36 = base SDK) ← **текущее решение** 2. Или патчить `source.properties`: `IsBaseSdk=true` + `package.xml`: `path="platforms;android-35"` ### Проблема: «Failed to find Build Tools revision 34.0.0» **Причина:** AGP 8.7.2 по умолчанию требует build-tools 34.0.0. При `sdkDownload=false` не может скачать. **Решение:** Явно указать установленную версию в `app/build.gradle` и глобально через `subprojects` в root `build.gradle`: ```groovy buildToolsVersion "35.0.1" ``` ### Проблема: Gradle зависает, прокси лог пустой (0 строк) **Причина:** Gradle обращается к `google()` / `mavenCentral()` напрямую, минуя прокси. **Решение:** Убрать `google()` и `mavenCentral()` из repositories. Оставить ТОЛЬКО proxy URLs. ### Проблема: SSH exit code 255 при pkill **Причина:** `pkill -f maven-proxy` совпадает с самой SSH командой и убивает сессию. **Решение:** ```bash ssh hunab-prod "ps aux | grep maven-proxy | grep python | grep -v grep | awk '{print \$2}' | xargs -r kill" ``` ### Проблема: Cursor tool timeout при сборке **Причина:** Gradle билд занимает ~1.5 мин, Cursor tool таймаутится через ~2 мин. **Решение:** Запускать в фоне: ```bash nohup bash -c ' cd /path/to/frontend/android ./gradlew bundleRelease --no-daemon --console=plain 2>&1 | tee /tmp/aab-build.log ' &>/dev/null & # Мониторинг tail -f /tmp/aab-build.log ``` ### Проблема: Однопоточный proxy таймаутится **Причина:** Python `http.server.HTTPServer` обрабатывает 1 запрос за раз. Gradle делает 10-50 параллельных запросов. **Решение:** `ThreadingMixIn`: ```python class S(socketserver.ThreadingMixIn, http.server.HTTPServer): daemon_threads = True allow_reuse_address = True ``` ### Проблема: Proxy возвращает 404 на HEAD запросы **Причина:** `BaseHTTPRequestHandler` по умолчанию не имеет `do_HEAD`. **Решение:** Добавить `do_HEAD`: ```python def do_HEAD(self): self._p('HEAD') ``` --- ## 📊 Версионирование ### Текущая версия (2026-02-28) | Параметр | Значение | |----------|----------| | versionName | 1.3.8 | | versionCode | 10308 | | compileSdkVersion | 36 | | targetSdkVersion | 35 | | minSdkVersion | 23 | | buildToolsVersion | 35.0.1 | | AGP | 8.7.2 | | Gradle | 8.11.1 | | Java | OpenJDK 21.0.9 | | Capacitor | 7.4.x | ### Для Google Play - **AAB файл:** `temp/android/hunab-app-v1.3.8-v10308-release.aab` - **Размер:** ~37 MB - **Подписан:** `hunab-app.keystore` (release signing config) - **Формат:** AAB (NEVER APK for Google Play!) - **versionCode** должен быть **больше** предыдущего релиза! ### Перед новым релизом 1. Обновить `versionCode` и `versionName` в `frontend/android/app/build.gradle` 2. Собрать фронтенд (`pnpm build`) 3. `npx cap sync android` 4. Следовать шагам 1-4 этого руководства --- ## 📁 Связанные файлы | Файл | Назначение | |------|------------| | `frontend/android/build.gradle` | Корневой Gradle — repos, plugins, subprojects override | | `frontend/android/app/build.gradle` | App модуль — version, signing, buildTools | | `frontend/android/gradle.properties` | JVM args, SDK download, TLS, suppressWarnings | | `frontend/android/variables.gradle` | compileSdk, targetSdk, dependency versions | | `docs/android/guides/SETUP_AND_BUILD_GUIDE.md` | **Общее руководство по установке и сборке** (для работы не из России) | | `docs/android/guides/EMULATOR_STARTUP_GUIDE.md` | **Полное руководство по запуску эмулятора** | | `docs/android/TROUBLESHOOTING.md` | Общий troubleshooting (включая другие проблемы) | | `docs/android/MOBILE_BUILD_REGULATIONS.md` | Регламент сборки мобильного приложения | | `scripts/android/quick-build-and-launch.sh` | Старый скрипт быстрой сборки (требует адаптации под proxy) | --- > **Последнее обновление:** 2026-02-28 > **Автор:** Aura (Cursor AI Agent) > **Проверено:** Успешная сборка AAB v1.3.8 (BUILD SUCCESSFUL in 1m 21s, 112 tasks)