Skip to content

模块配置

源:Android 官方文档 - 配置应用模块

本文档详细介绍如何配置 Android 应用模块的核心属性,包括 Application ID、Namespace、版本管理等关键配置。

Application ID

Application ID 是应用在设备和 Google Play 商店中的唯一标识符。修改 Application ID 会被视为发布一个全新的应用。

配置 Application ID

在模块级构建文件的 defaultConfig 块中设置:

kotlin
android {
    namespace = "com.example.myapp"
    
    defaultConfig {
        applicationId = "com.example.myapp"
        minSdk = 24
        targetSdk = 36
        versionCode = 1
        versionName = "1.0"
    }
}
groovy
android {
    namespace 'com.example.myapp'
    
    defaultConfig {
        applicationId 'com.example.myapp'
        minSdk 24
        targetSdk 36
        versionCode 1
        versionName '1.0'
    }
}

为不同构建变体设置 Application ID

可以为不同的构建类型或产品变种设置不同的 Application ID 后缀:

kotlin
android {
    defaultConfig {
        applicationId = "com.example.myapp"
    }
    
    buildTypes {
        debug {
            applicationIdSuffix = ".debug"
        }
        staging {
            applicationIdSuffix = ".staging"
        }
    }
    
    productFlavors {
        create("free") {
            applicationIdSuffix = ".free"
        }
        create("paid") {
            applicationIdSuffix = ".paid"
        }
    }
}
groovy
android {
    defaultConfig {
        applicationId 'com.example.myapp'
    }
    
    buildTypes {
        debug {
            applicationIdSuffix '.debug'
        }
        staging {
            applicationIdSuffix '.staging'
        }
    }
    
    productFlavors {
        free {
            applicationIdSuffix '.free'
        }
        paid {
            applicationIdSuffix '.paid'
        }
    }
}

示例结果

  • freeDebugcom.example.myapp.free.debug
  • paidDebugcom.example.myapp.paid.debug
  • freeReleasecom.example.myapp.free
  • paidReleasecom.example.myapp.paid

为测试配置 Application ID

测试 APK 的 Application ID 默认为应用 Application ID 加上 .test 后缀。可以通过 testApplicationId 属性自定义:

kotlin
android {
    defaultConfig {
        applicationId = "com.example.myapp"
        testApplicationId = "com.example.myapp.tests"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
}
groovy
android {
    defaultConfig {
        applicationId 'com.example.myapp'
        testApplicationId 'com.example.myapp.tests'
        testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
    }
}

Namespace AGP 7.0+

Namespace 用于生成应用的 R 类和 BuildConfig 类。从 AGP 7.0 开始,namespace 属性独立于 Application ID。

Namespace vs Package Name

在 AGP 7.0 之前,AndroidManifest.xml 中的 package 属性同时用于:

  1. 应用的唯一标识符
  2. R 类的包名

从 AGP 7.0 开始,这两个职责被分离:

  • applicationId(build.gradle):应用的唯一标识符
  • namespace(build.gradle):R 类和 BuildConfig 的包名
  • package(AndroidManifest.xml):仅用于解析相对类名

配置 Namespace AGP 8.0+ 必需

从 AGP 8.0 开始,必须在模块级构建文件中设置 namespace

kotlin
android {
    namespace = "com.example.myapp"
    
    defaultConfig {
        applicationId = "com.example.myapp.production"
    }
}
groovy
android {
    namespace 'com.example.myapp'
    
    defaultConfig {
        applicationId 'com.example.myapp.production'
    }
}

在上述示例中:

  • R 类将生成在 com.example.myapp 包中
  • 应用在设备上的唯一标识符是 com.example.myapp.production

迁移指南

如果你的项目仍在使用 AndroidManifest.xml 中的 package 属性,迁移步骤如下:

  1. 在 build.gradle 中添加 namespace
kotlin
android {
    namespace = "com.example.myapp" // 从 AndroidManifest.xml 复制
}
groovy
android {
    namespace 'com.example.myapp' // 从 AndroidManifest.xml 复制
}
  1. 简化 AndroidManifest.xml

迁移前

xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    
    <application>
        <activity android:name=".MainActivity" />
    </application>
</manifest>

迁移后

xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
    <application>
        <activity android:name="com.example.myapp.MainActivity" />
    </application>
</manifest>

或保留 package 仅用于解析相对类名:

xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    
    <application>
        <activity android:name=".MainActivity" />
    </application>
</manifest>

为测试配置 Namespace

测试模块也需要独立的 namespace:

kotlin
android {
    namespace = "com.example.myapp"
    
    testOptions {
        // 测试 namespace 默认为 "${namespace}.test"
        // 如需自定义:
        unitTests {
            // 单元测试配置
        }
    }
}
groovy
android {
    namespace 'com.example.myapp'
    
    testOptions {
        // 测试 namespace 默认为 "${namespace}.test"
        unitTests {
            // 单元测试配置
        }
    }
}

版本管理

Android 应用使用两个版本标识符:

versionCode

类型:整数
用途:内部版本号,用于版本比较和更新检测

Google Play 使用 versionCode 来确定一个版本是否比另一个版本新。每次发布更新时必须递增此值。

kotlin
android {
    defaultConfig {
        versionCode = 2
        versionName = "1.1.0"
    }
}
groovy
android {
    defaultConfig {
        versionCode 2
        versionName '1.1.0'
    }
}

最佳实践

  • 每次发布都递增 versionCode
  • 不同构建变体可以有不同的 versionCode
  • 建议使用连续递增的整数(1, 2, 3...)

versionName

类型:字符串
用途:面向用户的版本号,显示给用户

versionName 是用户看到的版本号,可以使用语义化版本(Semantic Versioning)格式:

<major>.<minor>.<patch>

示例:1.2.32.0.0-beta3.1.4-rc1

动态版本号

可以通过代码动态生成版本号:

kotlin
import java.text.SimpleDateFormat
import java.util.Date

android {
    defaultConfig {
        // 基于时间戳的 versionCode
        versionCode = SimpleDateFormat("yyyyMMdd").format(Date()).toInt()
        
        // 基于 Git 提交数的 versionCode
        versionCode = getGitCommitCount()
        
        // 组合版本名
        versionName = "1.0.${getGitCommitCount()}"
    }
}

fun getGitCommitCount(): Int {
    val stdout = java.io.ByteArrayOutputStream()
    exec {
        commandLine("git", "rev-list", "--count", "HEAD")
        standardOutput = stdout
    }
    return stdout.toString().trim().toInt()
}
groovy
import java.text.SimpleDateFormat

android {
    defaultConfig {
        // 基于时间戳的 versionCode
        versionCode new SimpleDateFormat('yyyyMMdd').format(new Date()).toInteger()
        
        // 基于 Git 提交数的 versionCode
        versionCode getGitCommitCount()
        
        // 组合版本名
        versionName "1.0.${getGitCommitCount()}"
    }
}

static def getGitCommitCount() {
    def stdout = new ByteArrayOutputStream()
    exec {
        commandLine 'git', 'rev-list', '--count', 'HEAD'
        standardOutput = stdout
    }
    return stdout.toString().trim().toInteger()
}

为不同变体设置版本

kotlin
android {
    defaultConfig {
        versionCode = 1
        versionName = "1.0"
    }
    
    productFlavors {
        create("free") {
            versionCode = 100
            versionName = "1.0-free"
        }
        create("paid") {
            versionCode = 200
            versionName = "1.0-paid"
        }
    }
}
groovy
android {
    defaultConfig {
        versionCode 1
        versionName '1.0'
    }
    
    productFlavors {
        free {
            versionCode 100
            versionName '1.0-free'
        }
        paid {
            versionCode 200
            versionName '1.0-paid'
        }
    }
}

compileSdk、minSdk、targetSdk

compileSdk

编译 SDK 版本决定了可以使用哪些 Android API。这不影响应用可以运行的最低 Android 版本。

kotlin
android {
    compileSdk = 36 // 或使用 API level
    
    // AGP 8.1+ 支持预览版 API
    compileSdkPreview = "VanillaIceCream"
}
groovy
android {
    compileSdk 36
    
    compileSdkPreview 'VanillaIceCream'
}

建议:始终使用最新的稳定版 API level。

minSdk

应用支持的最低 Android API level。低于此版本的设备无法安装应用。

kotlin
android {
    defaultConfig {
        minSdk = 24 // Android 7.0
    }
}
groovy
android {
    defaultConfig {
        minSdk 24
    }
}

选择建议

  • 参考 Android 版本分布
  • 平衡覆盖率与现代 API 可用性
  • 通常选择覆盖 95%+ 设备的版本

targetSdk

目标 SDK 版本表示应用已针对该版本进行测试。系统会为应用启用相应的行为变更。

kotlin
android {
    defaultConfig {
        targetSdk = 36
    }
}
groovy
android {
    defaultConfig {
        targetSdk 36
    }
}

重要性

  • Google Play 要求新应用和更新必须以最新 API level 为目标
  • 确保应用与最新 Android 版本的安全和隐私增强功能兼容

其他常用配置

多语言支持

限制应用中包含的语言资源以减小 APK 大小:

kotlin
android {
    defaultConfig {
        // 仅包含中文和英文资源
        resourceConfigurations += listOf("zh", "en")
    }
}
groovy
android {
    defaultConfig {
        resourceConfigurations += ['zh', 'en']
    }
}

矢量图配置

kotlin
android {
    defaultConfig {
        vectorDrawables {
            useSupportLibrary = true
            // 生成 PNG 密度
            generatedDensities += listOf("hdpi", "xxhdpi")
        }
    }
}
groovy
android {
    defaultConfig {
        vectorDrawables {
            useSupportLibrary true
            generatedDensities += ['hdpi', 'xxhdpi']
        }
    }
}

测试配置

kotlin
android {
    defaultConfig {
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        testApplicationId = "com.example.myapp.test"
        testHandleProfiling = true
        testFunctionalTest = true
    }
}
groovy
android {
    defaultConfig {
        testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
        testApplicationId 'com.example.myapp.test'
        testHandleProfiling true
        testFunctionalTest true
    }
}

最佳实践

  1. Application ID 不可变性:发布后不要更改 Application ID
  2. Namespace 迁移:尽早迁移到新的 namespace 配置方式
  3. 版本号规范:建立统一的版本号命名和递增规则
  4. Target SDK 更新:定期更新 targetSdk 以符合 Google Play 要求
  5. CompileSdk 最新化:使用最新稳定版 API level 编译
  6. MinSdk 平衡:在用户覆盖率和新特性之间找到平衡