Skip to content

AAB 构建与发布

源:Android 官方文档 - 关于 Android App Bundle

Android App Bundle (AAB) 是 Android 的官方发布格式,相比传统 APK 有更小的下载体积和更灵活的分发方式。

AAB 简介

什么是 AAB

AAB 是一种发布格式,包含应用的所有编译代码和资源,但将 APK 生成和签名交给 Google Play。

AAB vs APK

APK(传统)

  • 单一文件包含所有资源和代码
  • 体积大(包含所有语言、所有分辨率资源)
  • 用户下载完整 APK

AAB(推荐)

  • 仅发布时使用的格式
  • Google Play 根据设备生成优化的 APK
  • 用户仅下载设备需要的资源
  • 平均减少 15% 下载体积

AAB 的优势

更小的下载体积

  • 仅包含设备需要的代码和资源
  • 自动进行语言、屏幕密度、ABI 拆分

Dynamic Feature Modules

  • 按需下载功能模块
  • 减少初始安装体积

Asset Packs

  • 延迟下载大型资源(如游戏关卡)
  • 支持最大 2GB 的资源包

自动优化

  • Google Play 自动应用最新优化技术
  • 无需更新应用即可获得优化

构建 AAB

使用 Android Studio

BuildGenerate Signed Bundle / APK → 选择 Android App Bundle

使用 Gradle

bash
# 构建 release AAB
./gradlew bundleRelease

# 构建其他变体
./gradlew bundleDebug
./gradlew bundleDemoRelease

输出位置:

app/build/outputs/bundle/release/app-release.aab

配置混淆

AAB 同样需要 ProGuard/R8 配置:

kotlin
android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

配置语言和密度拆分

虽然 Google Play 会自动拆分,但可以配置默认拆分行为:

kotlin
android {
    bundle {
        language {
            // 禁用语言拆分(不推荐)
            enableSplit = false
        }
        
        density {
            // 禁用密度拆分(不推荐)
            enableSplit = false
        }
        
        abi {
            // 启用 ABI 拆分(默认启用)
            enableSplit = true
        }
    }
}

本地测试 AAB

使用 bundletool

bundletool 是官方命令行工具,用于从 AAB 生成 APK:

安装 bundletool

下载最新版本:https://github.com/google/bundletool/releases

生成 APK Sets

bash
java -jar bundletool.jar build-apks \
  --bundle=app-release.aab \
  --output=app-release.apks \
  --ks=keystore.jks \
  --ks-key-alias=key-alias

安装到设备

bash
# 安装适合连接设备的 APK
java -jar bundletool.jar install-apks \
  --apks=app-release.apks

提取特定配置的 APK

bash
# 提取中文 xxhdpi arm64 的 APK
java -jar bundletool.jar extract-apks \
  --apks=app-release.apks \
  --output-dir=output/ \
  --device-spec=device-spec.json

创建设备规范文件

device-spec.json

json
{
  "supportedAbis": ["arm64-v8a"],
  "supportedLocales": ["zh"],
  "screenDensity": 480,
  "sdkVersion": 30
}

上传到 Google Play

Play Console 上传

  1. 登录 Google Play Console
  2. 选择应用
  3. 发布生产版本(或其他轨道)
  4. 创建新版本
  5. 上传 AAB 文件
  6. 填写版本信息
  7. 审核并发布

使用 Gradle Play Publisher

自动化发布流程:

kotlin
plugins {
    id("com.github.triplet.play") version "3.9.0"
}

play {
    serviceAccountCredentials.set(file("service-account-key.json"))
    track.set("internal")  // internal, alpha, beta, production
    defaultToAppBundles.set(true)
}

发布:

bash
./gradlew publishReleaseBundle

Dynamic Feature Modules

创建 Dynamic Feature 模块

FileNewNew ModuleDynamic Feature Module

配置依赖

在 app 模块:

kotlin
// app/build.gradle.kts
android {
    dynamicFeatures += setOf(":feature_camera", ":feature_gallery")
}

在 feature 模块:

kotlin
// feature_camera/build.gradle.kts
plugins {
    id("com.android.dynamic-feature")
}

android {
    namespace = "com.example.feature.camera"
}

dependencies {
    implementation(project(":app"))
}

按需加载

kotlin
val splitInstallManager = SplitInstallManagerFactory.create(context)

val request = SplitInstallRequest.newBuilder()
    .addModule("feature_camera")
    .build()

splitInstallManager.startInstall(request)
    .addOnSuccessListener { sessionId ->
        // 开始下载
    }
    .addOnFailureListener { exception ->
        // 下载失败
    }

下载体积限制

压缩下载大小限制

  • 基础 APK + 配置 APK:150MB
  • 基础 + 所有 Dynamic Features:150MB

解决方案

  • 使用 Asset Packs 存储大型资源
  • 将功能拆分为 Dynamic Feature
  • 优化资源(WebP、矢量图)

最佳实践

始终使用 AAB

  • Google Play 已强制要求新应用使用 AAB
  • 不要继续使用 APK

测试所有配置

  • 使用 bundletool 测试不同设备配置
  • 检查拆分后的 APK 大小

合理使用 Dynamic Features

  • 仅在功能确实可选时使用
  • 避免过度拆分(影响用户体验)

保留 mapping 文件

  • AAB 同样需要 ProGuard mapping
  • 每个版本保存 mapping.txt

监控下载大小

  • Play Console 提供下载大小报告
  • 定期检查优化效果