# 🏗️ Сборка 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
<localPackage path="platforms;android-35" ...>   <!-- Было: platforms;android-35-ext15 -->
```

> ⚠️ Аналогичные изменения для 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)

