gplay-gradle-build

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Gradle Build for Google Play

面向Google Play的Gradle构建

Use this skill when you need to build an Android app before uploading to Play Store.
当你需要在上传至Play Store前构建Android应用时,可使用本技能。

Build Types

构建类型

App Bundle (AAB) - Recommended

App Bundle (AAB) - 推荐方案

App Bundles are required for new apps on Google Play:
bash
./gradlew bundleRelease
Output:
app/build/outputs/bundle/release/app-release.aab
Google Play要求新应用必须使用App Bundle:
bash
./gradlew bundleRelease
输出路径:
app/build/outputs/bundle/release/app-release.aab

APK - Legacy

APK - 传统格式

For apps not using bundles:
bash
./gradlew assembleRelease
Output:
app/build/outputs/apk/release/app-release.apk
适用于未采用App Bundle的应用:
bash
./gradlew assembleRelease
输出路径:
app/build/outputs/apk/release/app-release.apk

Signing Configuration

签名配置

build.gradle (app level)

应用级build.gradle

groovy
android {
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE_FILE") ?: "release.keystore")
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword System.getenv("KEY_PASSWORD")
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
groovy
android {
    signingConfigs {
        release {
            storeFile file(System.getenv("KEYSTORE_FILE") ?: "release.keystore")
            storePassword System.getenv("KEYSTORE_PASSWORD")
            keyAlias System.getenv("KEY_ALIAS")
            keyPassword System.getenv("KEY_PASSWORD")
        }
    }

    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

Environment Variables

环境变量配置

bash
export KEYSTORE_FILE=/path/to/release.keystore
export KEYSTORE_PASSWORD=your_keystore_password
export KEY_ALIAS=your_key_alias
export KEY_PASSWORD=your_key_password

./gradlew bundleRelease
bash
export KEYSTORE_FILE=/path/to/release.keystore
export KEYSTORE_PASSWORD=your_keystore_password
export KEY_ALIAS=your_key_alias
export KEY_PASSWORD=your_key_password

./gradlew bundleRelease

Version Management

版本管理

gradle.properties

gradle.properties

properties
VERSION_NAME=1.2.3
VERSION_CODE=123
properties
VERSION_NAME=1.2.3
VERSION_CODE=123

build.gradle

build.gradle

groovy
android {
    defaultConfig {
        versionCode project.property('VERSION_CODE').toInteger()
        versionName project.property('VERSION_NAME')
    }
}
groovy
android {
    defaultConfig {
        versionCode project.property('VERSION_CODE').toInteger()
        versionName project.property('VERSION_NAME')
    }
}

Increment version

版本号自增

bash
undefined
bash
undefined

Read current version

读取当前版本号

CURRENT_VERSION=$(grep VERSION_CODE gradle.properties | cut -d'=' -f2) NEW_VERSION=$((CURRENT_VERSION + 1))
CURRENT_VERSION=$(grep VERSION_CODE gradle.properties | cut -d'=' -f2) NEW_VERSION=$((CURRENT_VERSION + 1))

Update gradle.properties

更新gradle.properties

sed -i "" "s/VERSION_CODE=$CURRENT_VERSION/VERSION_CODE=$NEW_VERSION/" gradle.properties
sed -i "" "s/VERSION_CODE=$CURRENT_VERSION/VERSION_CODE=$NEW_VERSION/" gradle.properties

Build

构建应用

./gradlew bundleRelease
undefined
./gradlew bundleRelease
undefined

ProGuard/R8 Configuration

ProGuard/R8配置

Enable R8 (default in AGP 3.4+)

启用R8(AGP 3.4+默认启用)

groovy
buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
groovy
buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

Generate mapping file

生成映射文件

Mapping file location:
app/build/outputs/mapping/release/mapping.txt
Upload to Play Console for crash symbolication:
bash
gplay deobfuscation upload \
  --package com.example.app \
  --edit $EDIT_ID \
  --apk-version 123 \
  --type proguard \
  --file app/build/outputs/mapping/release/mapping.txt
映射文件路径:
app/build/outputs/mapping/release/mapping.txt
上传至Play Console以解析崩溃信息:
bash
gplay deobfuscation upload \
  --package com.example.app \
  --edit $EDIT_ID \
  --apk-version 123 \
  --type proguard \
  --file app/build/outputs/mapping/release/mapping.txt

Build Variants

构建变体

Product Flavors

产品风味

groovy
android {
    flavorDimensions "version"
    productFlavors {
        free {
            dimension "version"
            applicationIdSuffix ".free"
        }
        paid {
            dimension "version"
        }
    }
}
groovy
android {
    flavorDimensions "version"
    productFlavors {
        free {
            dimension "version"
            applicationIdSuffix ".free"
        }
        paid {
            dimension "version"
        }
    }
}

Build specific flavor

构建指定风味的应用

bash
./gradlew bundleFreeRelease
./gradlew bundlePaidRelease
bash
./gradlew bundleFreeRelease
./gradlew bundlePaidRelease

CI/CD Build

CI/CD构建

GitHub Actions Example

GitHub Actions示例

yaml
- name: Build Release AAB
  run: |
    echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore
    export KEYSTORE_FILE=release.keystore
    export KEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}"
    export KEY_ALIAS="${{ secrets.KEY_ALIAS }}"
    export KEY_PASSWORD="${{ secrets.KEY_PASSWORD }}"
    ./gradlew bundleRelease

- name: Upload to Play Store
  env:
    GPLAY_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
  run: |
    gplay release \
      --package com.example.app \
      --track internal \
      --bundle app/build/outputs/bundle/release/app-release.aab
yaml
- name: Build Release AAB
  run: |
    echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore
    export KEYSTORE_FILE=release.keystore
    export KEYSTORE_PASSWORD="${{ secrets.KEYSTORE_PASSWORD }}"
    export KEY_ALIAS="${{ secrets.KEY_ALIAS }}"
    export KEY_PASSWORD="${{ secrets.KEY_PASSWORD }}"
    ./gradlew bundleRelease

- name: Upload to Play Store
  env:
    GPLAY_SERVICE_ACCOUNT: ${{ secrets.PLAY_SERVICE_ACCOUNT }}
  run: |
    gplay release \
      --package com.example.app \
      --track internal \
      --bundle app/build/outputs/bundle/release/app-release.aab

Common Build Tasks

常见构建任务

Clean build

清理后构建

bash
./gradlew clean bundleRelease
bash
./gradlew clean bundleRelease

Build with specific SDK versions

指定SDK版本构建

bash
./gradlew bundleRelease -PminSdkVersion=21 -PtargetSdkVersion=34
bash
./gradlew bundleRelease -PminSdkVersion=21 -PtargetSdkVersion=34

Build without tests

跳过测试构建

bash
./gradlew bundleRelease -x test -x lint
bash
./gradlew bundleRelease -x test -x lint

Build multiple variants

构建所有变体

bash
./gradlew bundle  # Builds all variants
bash
./gradlew bundle  # 构建所有变体

Troubleshooting

故障排查

Build fails with signing errors

构建因签名错误失败

bash
undefined
bash
undefined

Verify keystore

验证密钥库

keytool -list -v -keystore release.keystore
undefined
keytool -list -v -keystore release.keystore
undefined

Check AAB contents

检查AAB内容

bash
bundletool build-apks \
  --bundle=app-release.aab \
  --output=output.apks \
  --mode=universal

unzip output.apks
bash
bundletool build-apks \
  --bundle=app-release.aab \
  --output=output.apks \
  --mode=universal

unzip output.apks

Verify version codes

验证版本号

bash
./gradlew tasks --all | grep Version
bash
./gradlew tasks --all | grep Version

Best Practices

最佳实践

  1. Never commit keystores - Store in secure location
  2. Use environment variables for credentials
  3. Enable ProGuard/R8 for release builds
  4. Upload mapping files after each release
  5. Increment version code for every build
  6. Test release builds before uploading
  7. Use App Bundles (AAB) instead of APKs when possible
  1. 切勿提交密钥库 - 存储在安全位置
  2. 使用环境变量管理凭证
  3. 发布构建启用ProGuard/R8
  4. 每次发布后上传映射文件
  5. 每次构建自增版本号
  6. 上传前测试发布构建
  7. 尽可能使用App Bundles (AAB)替代APKs