我正在从 Ant/Eclipse 环境迁移到 Gradle/Android Studio,我们使用的一些工具需要 Android 应用程序具有包含 android:name 和 android:value 字段集的元数据标签。
我们目前有两个应用程序的构建变体,在 build.gradle 文件中指定为 ProductFlavours/buildTypes。 由于Android的manifest.xml文件是由gradle在构建时生成的,我显然不能直接将元数据直接放入xml文件中。
有没有办法在 build.gradle 文件中指定这一点,以便两个 buildType 都将元数据字段添加到生成的 Manifest.xml 中,但具有不同的“android:value”值?
您可以使用这种方法:
buildTypes {
debug {
...
resValue "string", "my_string", "string value debug"
}
release {
...
resValue "string", "my_string", "string value release"
}
}
或
productFlavors {
staging {
...
resValue "string", "my_string", "string value staging"
}
production {
...
resValue "string", "my_string", "string value production"
}
}
<meta-data android:name="MY_META" android:value="@string/my_string"/>
受到其他一些答案的启发,这效果很好......
1)在清单中放置一个占位符:
<meta-data android:name="MY_META" android:value="${someKeyForValue}"/>
2)在你的build.gradle中设置值
flavorDimensions "env"
productFlavors {
dev {
flavorDimension "env"
...
someKeyForValue = "TheDynamicValue_01"
}
prod {
flavorDimension "env"
...
someKeyForValue = "TheDynamicValue_02"
}
}
这种方法避免了创建资源,并且原始清单读起来更清楚,将在构建时注入一个值。
有关清单占位符支持的更多信息:Android 工具和清单占位符
为什么不能将
meta-data
直接放在清单中?
您可以通过
buildTypes
为每个 gradle sourceSets
指定一个清单:
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
res.srcDirs = ['src/main/res']
}
debug {
manifest.srcFile 'src/main/debug/AndroidManifest.xml'
res.srcDirs = ['src/main/debug/res']
}
release {
manifest.srcFile 'src/main/release/AndroidManifest.xml'
res.srcDirs = ['src/main/release/res']
}
}
如果您在调试中构建,gradle 会将“主”清单与调试清单合并。
android {
...
buildTypes {
debug {
...
resValue "string", "GOOGLE_MAPS_ANDROID_API_KEY", "(your development Maps API key)"
}
release {
...
resValue "string", "GOOGLE_MAPS_ANDROID_API_KEY", "(your production Maps API key)"
}
}
}
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="@string/GOOGLE_MAPS_ANDROID_API_KEY"/>
Your IDE may complain about this string resource not existing, but it will build just fine.
AGP 8.6 及以上版本的替代方法是使用
addGeneratedManifestFile()
。
以下示例展示了如何根据当前构建类型启用/禁用未捕获异常的 Crashlytics 运行时收集:
plugins.withId("com.android.base") {
extensions.findByType(AndroidComponentsExtension::class.java)?.apply {
configureAndroidComponents()
}
}
fun AndroidComponentsExtension<*, *, *>.configureAndroidComponents() {
onVariants { variant ->
project.generateTask(variant)
}
}
private fun Project.generateTask(variant: Variant) {
val taskName = "generate${variant.name.capitalized()}CrashlyticsManifest"
val taskProvider = project.tasks.register(taskName, EnableFirebaseCrashlyticsTask::class.java) {
enable.set(variant.buildType == "release")
}
variant.sources.manifests.addGeneratedManifestFile(taskProvider, EnableFirebaseCrashlyticsTask::manifest)
}
abstract class EnableFirebaseCrashlyticsTask : DefaultTask() {
@get:Input
abstract val enable: Property<Boolean>
@get:OutputFile
abstract val manifest: RegularFileProperty
@TaskAction
fun run() {
manifest.get().asFile.writeText(
"""
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="${enable.get()}" />
</application>
</manifest>
""".trimIndent()
)
}
}
生成的清单文件放在
build/generated/manifests/generate<BuildVariant>CrashlyticsManifest/AndroidManifest.xml
下面。