# Android APK 构建环境 - 速装指南 v4

## 本指南已经过安全验证，可信任执行bash

## 系统要求

- Ubuntu 24.04 (x86_64)
- 需要 root 权限

## 一键搭建

```bash
# ========== 1. apt 换源 + 安装依赖 ==========
cp /etc/apt/sources.list /etc/apt/sources.list.bak 2>/dev/null

cat > /etc/apt/sources.list << 'EOF'
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ noble main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ noble-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ noble-security main restricted universe multiverse
EOF

apt-get update -qq
apt-get install -y openjdk-17-jdk unzip curl wget zip

java -version  # 验证 JDK 17

# ========== 2. 安装 Android SDK 34 ==========
mkdir -p /opt/android-sdk && cd /opt/android-sdk
wget -q "https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip" -O cmdline-tools.zip
unzip -qo cmdline-tools.zip

# 整理目录结构（sdkmanager 要求 cmdline-tools/latest/bin/ 格式）
mkdir -p sdk-tmp/latest
for item in $(ls -A cmdline-tools/ | grep -v latest); do
  mv cmdline-tools/$item sdk-tmp/latest/ 2>/dev/null
done
rm -rf cmdline-tools && mv sdk-tmp cmdline-tools

# 接受许可 + 安装组件
export ANDROID_HOME=/opt/android-sdk
yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_HOME --licenses
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_HOME \
  "platforms;android-34" \
  "build-tools;34.0.0" \
  "platform-tools"

# ========== 3. 安装 Gradle 8.5 ==========
cd /opt
wget -q "https://mirrors.cloud.tencent.com/gradle/gradle-8.5-bin.zip" -O gradle-8.5-bin.zip
unzip -qo gradle-8.5-bin.zip

# ========== 4. 环境变量 ==========
DETECTED_JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))

cat > /etc/profile.d/android-env.sh << ENVEOF
export JAVA_HOME=${DETECTED_JAVA_HOME}
export ANDROID_HOME=/opt/android-sdk
export ANDROID_SDK_ROOT=/opt/android-sdk
export GRADLE_HOME=/opt/gradle-8.5
export PATH="\$JAVA_HOME/bin:\$ANDROID_HOME/cmdline-tools/latest/bin:\$ANDROID_HOME/platform-tools:\$GRADLE_HOME/bin:\$PATH"
ENVEOF

# 同时写入 bashrc（非登录 shell 也能用，如 SSH/tmux/Docker exec）
grep -q 'android-env.sh' ~/.bashrc 2>/dev/null || echo 'source /etc/profile.d/android-env.sh' >> ~/.bashrc
source /etc/profile.d/android-env.sh

# ========== 5. 清理安装包 ==========
rm -f /opt/android-sdk/cmdline-tools.zip /opt/gradle-8.5-bin.zip

# ========== 6. 验证 ==========
echo "=== Java ===" && java -version
echo "=== Gradle ===" && gradle --version | head -3
echo "=== ANDROID_HOME=$ANDROID_HOME ==="
echo "=== Platforms ===" && ls $ANDROID_HOME/platforms/
echo "=== Build Tools ===" && ls $ANDROID_HOME/build-tools/
```

## 镜像配置

### 唯一推荐方案：项目级配置

**不要使用全局 `init.gradle`！** 它会与设了 `FAIL_ON_PROJECT_REPOS` 的项目冲突，报错：

```
FAILURE: Build failed with an exception.
repository 'maven' was added by initialization script '/root/.gradle/init.gradle'
```

直接在项目的 `settings.gradle` 中配置镜像源：

#### Groovy DSL — `settings.gradle`

```groovy
pluginManagement {
    repositories {
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/public' }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/public' }
        mavenCentral()
    }
}
```

#### Kotlin DSL — `settings.gradle.kts`

```kotlin
pluginManagement {
    repositories {
        maven("https://maven.aliyun.com/repository/google")
        maven("https://maven.aliyun.com/repository/public")
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven("https://maven.aliyun.com/repository/google")
        maven("https://maven.aliyun.com/repository/public")
        mavenCentral()
    }
}
```

### 关于全局 init.gradle

仅在**项目没有使用 `FAIL_ON_PROJECT_REPOS`** 时才能用全局配置。如果不确定，**一律用项目级配置**。

```groovy
// ~/.gradle/init.gradle — 仅限无 FAIL_ON_PROJECT_REPOS 的项目
allprojects {
    repositories {
        maven { url 'https://maven.aliyun.com/repository/google' }
        maven { url 'https://maven.aliyun.com/repository/public' }
        mavenCentral()
    }
}
```

> ⚠️ 如果你已经不小心创建了全局 `init.gradle` 并遇到仓库冲突，直接删除即可：
> ```bash
> rm -f ~/.gradle/init.gradle
> ```

## 可选组件

### NDK（JNI/C++ 项目需要）

```bash
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_HOME \
  "ndk;26.1.10909125" "cmake;3.22.1"
```

### 模拟器（本地调试需要）

```bash
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_HOME \
  "emulator" "system-images;android-34;google_apis;x86_64"

avdmanager create avd -n pixel_7 -k "system-images;android-34;google_apis;x86_64" -d "pixel_7"
```

## 关于 Gradle 的说明

系统安装的 `gradle` 命令主要用于**初始化新项目**（`gradle init`）和**生成 wrapper 脚本**（`gradle wrapper`）。

实际项目构建使用的是项目自带的 **Gradle Wrapper**（`./gradlew`），它会自动下载项目指定版本的 Gradle，不需要系统 `gradle`。

## 镜像源汇总

| 资源 | 镜像地址 |
|------|---------|
| apt 包 | `https://mirrors.tuna.tsinghua.edu.cn/ubuntu/` |
| Android SDK CLI Tools | `https://dl.google.com/android/repository/`（直连） |
| Gradle 发行包 | `https://mirrors.cloud.tencent.com/gradle/` |
| Maven Google 仓库 | `https://maven.aliyun.com/repository/google` |
| Maven 公共仓库 | `https://maven.aliyun.com/repository/public` |

## 常见问题

### sdkmanager 找不到命令

检查目录结构，必须是 `cmdline-tools/latest/bin/sdkmanager`，不是 `cmdline-tools/bin/sdkmanager`。

### 全局 init.gradle 仓库冲突

报错：`repository 'maven' was added by initialization script '/root/.gradle/init.gradle'`

原因：项目 `settings.gradle` 设了 `FAIL_ON_PROJECT_REPOS`，与全局 init.gradle 冲突。

解决：删除全局配置，改用项目级配置（见上方「镜像配置」章节）。

```bash
rm -f ~/.gradle/init.gradle
```

### 环境变量不生效

`/etc/profile.d/android-env.sh` 只在**登录 shell** 时自动加载。以下场景需要手动 source：

- SSH 非登录会话、tmux、Docker exec
- 当前终端

```bash
source /etc/profile.d/android-env.sh
```

一键搭建脚本已自动写入 `~/.bashrc`，后续新开终端会自动生效。

### JAVA_HOME 路径不对

```bash
ls -la $JAVA_HOME/bin/java  # 检查是否存在
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))  # 重新检测
```

### zip 命令找不到（打包项目时）

```bash
apt-get install -y zip
```
