模块配置
本文档详细介绍如何配置 Android 应用模块的核心属性,包括 Application ID、Namespace、版本管理等关键配置。
Application ID
Application ID 是应用在设备和 Google Play 商店中的唯一标识符。修改 Application ID 会被视为发布一个全新的应用。
配置 Application ID
在模块级构建文件的 defaultConfig 块中设置:
android {
namespace = "com.example.myapp"
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 36
versionCode = 1
versionName = "1.0"
}
}android {
namespace 'com.example.myapp'
defaultConfig {
applicationId 'com.example.myapp'
minSdk 24
targetSdk 36
versionCode 1
versionName '1.0'
}
}为不同构建变体设置 Application ID
可以为不同的构建类型或产品变种设置不同的 Application ID 后缀:
android {
defaultConfig {
applicationId = "com.example.myapp"
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
}
staging {
applicationIdSuffix = ".staging"
}
}
productFlavors {
create("free") {
applicationIdSuffix = ".free"
}
create("paid") {
applicationIdSuffix = ".paid"
}
}
}android {
defaultConfig {
applicationId 'com.example.myapp'
}
buildTypes {
debug {
applicationIdSuffix '.debug'
}
staging {
applicationIdSuffix '.staging'
}
}
productFlavors {
free {
applicationIdSuffix '.free'
}
paid {
applicationIdSuffix '.paid'
}
}
}示例结果:
freeDebug→com.example.myapp.free.debugpaidDebug→com.example.myapp.paid.debugfreeRelease→com.example.myapp.freepaidRelease→com.example.myapp.paid
为测试配置 Application ID
测试 APK 的 Application ID 默认为应用 Application ID 加上 .test 后缀。可以通过 testApplicationId 属性自定义:
android {
defaultConfig {
applicationId = "com.example.myapp"
testApplicationId = "com.example.myapp.tests"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}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 属性同时用于:
- 应用的唯一标识符
- R 类的包名
从 AGP 7.0 开始,这两个职责被分离:
applicationId(build.gradle):应用的唯一标识符namespace(build.gradle):R 类和 BuildConfig 的包名package(AndroidManifest.xml):仅用于解析相对类名
配置 Namespace AGP 8.0+ 必需
从 AGP 8.0 开始,必须在模块级构建文件中设置 namespace:
android {
namespace = "com.example.myapp"
defaultConfig {
applicationId = "com.example.myapp.production"
}
}android {
namespace 'com.example.myapp'
defaultConfig {
applicationId 'com.example.myapp.production'
}
}在上述示例中:
- R 类将生成在
com.example.myapp包中 - 应用在设备上的唯一标识符是
com.example.myapp.production
迁移指南
如果你的项目仍在使用 AndroidManifest.xml 中的 package 属性,迁移步骤如下:
- 在 build.gradle 中添加
namespace:
android {
namespace = "com.example.myapp" // 从 AndroidManifest.xml 复制
}android {
namespace 'com.example.myapp' // 从 AndroidManifest.xml 复制
}- 简化 AndroidManifest.xml:
迁移前:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application>
<activity android:name=".MainActivity" />
</application>
</manifest>迁移后:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name="com.example.myapp.MainActivity" />
</application>
</manifest>或保留 package 仅用于解析相对类名:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application>
<activity android:name=".MainActivity" />
</application>
</manifest>为测试配置 Namespace
测试模块也需要独立的 namespace:
android {
namespace = "com.example.myapp"
testOptions {
// 测试 namespace 默认为 "${namespace}.test"
// 如需自定义:
unitTests {
// 单元测试配置
}
}
}android {
namespace 'com.example.myapp'
testOptions {
// 测试 namespace 默认为 "${namespace}.test"
unitTests {
// 单元测试配置
}
}
}版本管理
Android 应用使用两个版本标识符:
versionCode
类型:整数
用途:内部版本号,用于版本比较和更新检测
Google Play 使用 versionCode 来确定一个版本是否比另一个版本新。每次发布更新时必须递增此值。
android {
defaultConfig {
versionCode = 2
versionName = "1.1.0"
}
}android {
defaultConfig {
versionCode 2
versionName '1.1.0'
}
}最佳实践:
- 每次发布都递增
versionCode - 不同构建变体可以有不同的
versionCode - 建议使用连续递增的整数(1, 2, 3...)
versionName
类型:字符串
用途:面向用户的版本号,显示给用户
versionName 是用户看到的版本号,可以使用语义化版本(Semantic Versioning)格式:
<major>.<minor>.<patch>示例:1.2.3、2.0.0-beta、3.1.4-rc1
动态版本号
可以通过代码动态生成版本号:
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()
}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()
}为不同变体设置版本
android {
defaultConfig {
versionCode = 1
versionName = "1.0"
}
productFlavors {
create("free") {
versionCode = 100
versionName = "1.0-free"
}
create("paid") {
versionCode = 200
versionName = "1.0-paid"
}
}
}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 版本。
android {
compileSdk = 36 // 或使用 API level
// AGP 8.1+ 支持预览版 API
compileSdkPreview = "VanillaIceCream"
}android {
compileSdk 36
compileSdkPreview 'VanillaIceCream'
}建议:始终使用最新的稳定版 API level。
minSdk
应用支持的最低 Android API level。低于此版本的设备无法安装应用。
android {
defaultConfig {
minSdk = 24 // Android 7.0
}
}android {
defaultConfig {
minSdk 24
}
}选择建议:
- 参考 Android 版本分布
- 平衡覆盖率与现代 API 可用性
- 通常选择覆盖 95%+ 设备的版本
targetSdk
目标 SDK 版本表示应用已针对该版本进行测试。系统会为应用启用相应的行为变更。
android {
defaultConfig {
targetSdk = 36
}
}android {
defaultConfig {
targetSdk 36
}
}重要性:
- Google Play 要求新应用和更新必须以最新 API level 为目标
- 确保应用与最新 Android 版本的安全和隐私增强功能兼容
其他常用配置
多语言支持
限制应用中包含的语言资源以减小 APK 大小:
android {
defaultConfig {
// 仅包含中文和英文资源
resourceConfigurations += listOf("zh", "en")
}
}android {
defaultConfig {
resourceConfigurations += ['zh', 'en']
}
}矢量图配置
android {
defaultConfig {
vectorDrawables {
useSupportLibrary = true
// 生成 PNG 密度
generatedDensities += listOf("hdpi", "xxhdpi")
}
}
}android {
defaultConfig {
vectorDrawables {
useSupportLibrary true
generatedDensities += ['hdpi', 'xxhdpi']
}
}
}测试配置
android {
defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testApplicationId = "com.example.myapp.test"
testHandleProfiling = true
testFunctionalTest = true
}
}android {
defaultConfig {
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
testApplicationId 'com.example.myapp.test'
testHandleProfiling true
testFunctionalTest true
}
}最佳实践
- Application ID 不可变性:发布后不要更改 Application ID
- Namespace 迁移:尽早迁移到新的 namespace 配置方式
- 版本号规范:建立统一的版本号命名和递增规则
- Target SDK 更新:定期更新 targetSdk 以符合 Google Play 要求
- CompileSdk 最新化:使用最新稳定版 API level 编译
- MinSdk 平衡:在用户覆盖率和新特性之间找到平衡