为每个构建变体使用不同的 manifestPlaceholder
Using a different manifestPlaceholder for each Build Variant
首先我要说我是 Gradle 的新手,所以如果有人回答了这个问题,我深表歉意。
我正在开发一个 Android 应用程序,该应用程序使用 API 密钥访问第 3 方工具。根据应用程序的 flavor 和 build type,需要使用不同的 API 密钥。
这是我正在尝试做的事情的基本概述:
android {
defaultConfig {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
buildTypes{
debug{
// Some debug setup
}
release{
// Some release setup
}
}
productFlavors {
// List of flavor options
}
productFlavors.all{ flavor->
if (flavor.name.equals("someFlavor")) {
if (buildType.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_1" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
} else {
if (buildType.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_2" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
}
}
}
到目前为止,manifestPlaceholders
语句在一个非常简单的情况下工作,但我不知道如何从 中引用 buildType ]productFlavors 块,以便我可以将其用作条件。
我相信您需要一个 manifestPlaceHolder 来读取 Java 代码中的值,对吧?如果是这种情况,您已经可以在生成的 BuildConfig.java 中读取 FLAVOR 名称。例如,如果您定义了一个名为 smartphone 的 flavor,您可以使用 BuildConfig.FLAVOR String 访问该值;然后在你的代码中你可以使用一个简单的 if (BuildConfig.FLAVOR.equals("smartphone"))...
但也许您需要阅读您的应用程序的一种配置,即 apiKey。在这种情况下,最好的方法是为每种口味创建一个 Class 或一个字符串资源;这是给你的link。
我猜你指的是 Fabric ApiKey? :) 我只是花了几个小时尝试以类似的方式使用占位符并在 gradle 文件中指定 ApiKey,尽管从 com.android.tools.build:gradle:1.3.1
开始似乎不可能。可以为特定风味指定占位符,但不能为风味和构建类型指定占位符。
只是为了纠正你的语法,你必须这样做的方式(如果可能的话)应该是这样的,但是 manifestPlaceholders 对变体来说是未知的。
applicationVariants.all{ variant->
if (variant.productFlavors.get(0).name.equals("someFlavor")) {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_1" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
} else {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_2" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
}
}
您实际需要做的是将密钥保存在 AndroidManifest.xml
中并使用多个清单文件处理它
src/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="DEBUG_KEY" tools:replace="android:value"/>
</application>
</manifest>
src/someFlavorRelease/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="RELEASE_KEY_1" tools:replace="android:value"/>
</application>
</manifest>
src/someOtherFlavorRelease/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="RELEASE_KEY_2" tools:replace="android:value"/>
</application>
</manifest>
manifestMerger 将处理替换,您将在每个场景中得到正确的密钥。我刚刚成功实施了它。我只是希望你真的指的是 Fabric 键! :)
希望对您有所帮助!
与接受的答案类似,如果您不想复制您的清单,您可以使用字符串资源来完成。
例如,如果您有两种口味(口味 1 和口味 2)
您最终会得到以下源集。
app/
src/
main/
res/
values/strings.xml
flavor1Release/
res/
values/strings.xml
flavor1Debug/
res/
values/strings.xml
flavor2Release/
res/
values/strings.xml
flavor2Debug/
res/
values/strings.xml
然后您可以只使用字符串资源作为您的键值
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="@string/apiKey" tools:replace="android:value"/>
</application>
</manifest>
将所有密钥保存在一个地方的进一步优化是在主源集中的 strings.xml 中定义它们。然后让 flavor/build 源集引用那些。
例如:
<resources>
<string name="flavor1ReleaseKey">flavor1ReleaseKey</string>
<string name="flavor1DebugKey">flavor1DebugKey</string>
<string name="flavor2ReleaseKey">flavor2ReleaseKey</string>
<string name="flavor2DebugKey">flavor2DebugKey</string>
</resources>
然后在每个 flavor/build sourceSets 中,您只需引用这些键。
flavor1Release/res/values/strings.xml
<resources>
<string name="apiKey">@string/flavor1ReleaseKey</string>
</resources>
您可以通过访问特定 applicationVariant 的 mergedFlavor 在 applicationVariants 中设置 manifestPlaceholders。
android.applicationVariants.all { variant ->
def mergedFlavor = variant.getMergedFlavor()
mergedFlavor.manifestPlaceholders = [appPackageId: "myPackageExample"]
}
如果你使用的是 Kotlin DSL,你应该使用这样的东西:
android.applicationVariants.all { // don't put 'variant ->' here or you'll get the 'all' extension function
// no need to define 'mergedFlavor' because 'this' _is_ the variant so 'mergedFlavor' is already available.
mergedFlavor.manifestPlaceholders = ...
}
我所做的是将当前 AndroidManifest.xml
复制到 app/src/debug
并更改了调试清单中的密钥:
<meta-data
android:name="com.crashlytics.ApiKey"
tools:replace="android:value"
android:value="@string/crashlytics_debug" />
app/src/main
清单就像:
<meta-data
android:name="com.crashlytics.ApiKey"
android:value="@string/crashlytics_live" />
我在 https://azabost.com/android-manifest-placeholders/
中找到了这个很棒的解决方案
android {
...
buildTypes {
release {
...
manifestPlaceholders.screenOrientation = "portrait"
}
debug {...}
}
}
或
android {
...
flavorDimensions "features"
productFlavors {
paid {
dimension "features"
manifestPlaceholders.hostName = "www.paid-example.com"
}
free {
dimension "features"
manifestPlaceholders.hostName = "www.free-example.com"
}
}
您不需要重复的文件
Build.gradle
productFlavors {
prod {
applicationId "com.example.prod"
dimension "mode"
manifestPlaceholders = [hostName:"some String"]
}
dev {
applicationId "com.example.dev"
dimension "mode"
manifestPlaceholders = [hostName:"some String"]
}
最明显的使用“${hostName}”。下面的例子
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${hostName}" />
作为@Eric post 的补充,对于 AGP 版本 com.android.tools.build:gradle:4.x
,此代码片段
applicationVariants.all{ variant->
if (variant.productFlavors.get(0).name.equals("someFlavor")) {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_1" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
} else {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_2" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
}
}
应更新为
androidComponents {
onVariants(selector().withBuildType("debug")) {
manifestPlaceholders.apiKey = "DEBUG_KEY"
}
onVariants(selector().withBuildType("release")) {
if(flavorName.equals("someFlavor"))
manifestPlaceholders.apiKey = "RELEASE_KEY_1"
else
manifestPlaceholders.apiKey = "RELEASE_KEY_2"
}
}
首先我要说我是 Gradle 的新手,所以如果有人回答了这个问题,我深表歉意。
我正在开发一个 Android 应用程序,该应用程序使用 API 密钥访问第 3 方工具。根据应用程序的 flavor 和 build type,需要使用不同的 API 密钥。
这是我正在尝试做的事情的基本概述:
android {
defaultConfig {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
buildTypes{
debug{
// Some debug setup
}
release{
// Some release setup
}
}
productFlavors {
// List of flavor options
}
productFlavors.all{ flavor->
if (flavor.name.equals("someFlavor")) {
if (buildType.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_1" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
} else {
if (buildType.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_2" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
}
}
}
到目前为止,manifestPlaceholders
语句在一个非常简单的情况下工作,但我不知道如何从 中引用 buildType ]productFlavors 块,以便我可以将其用作条件。
我相信您需要一个 manifestPlaceHolder 来读取 Java 代码中的值,对吧?如果是这种情况,您已经可以在生成的 BuildConfig.java 中读取 FLAVOR 名称。例如,如果您定义了一个名为 smartphone 的 flavor,您可以使用 BuildConfig.FLAVOR String 访问该值;然后在你的代码中你可以使用一个简单的 if (BuildConfig.FLAVOR.equals("smartphone"))...
但也许您需要阅读您的应用程序的一种配置,即 apiKey。在这种情况下,最好的方法是为每种口味创建一个 Class 或一个字符串资源;这是给你的link。
我猜你指的是 Fabric ApiKey? :) 我只是花了几个小时尝试以类似的方式使用占位符并在 gradle 文件中指定 ApiKey,尽管从 com.android.tools.build:gradle:1.3.1
开始似乎不可能。可以为特定风味指定占位符,但不能为风味和构建类型指定占位符。
只是为了纠正你的语法,你必须这样做的方式(如果可能的话)应该是这样的,但是 manifestPlaceholders 对变体来说是未知的。
applicationVariants.all{ variant->
if (variant.productFlavors.get(0).name.equals("someFlavor")) {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_1" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
} else {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_2" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
}
}
您实际需要做的是将密钥保存在 AndroidManifest.xml
中并使用多个清单文件处理它
src/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="DEBUG_KEY" tools:replace="android:value"/>
</application>
</manifest>
src/someFlavorRelease/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="RELEASE_KEY_1" tools:replace="android:value"/>
</application>
</manifest>
src/someOtherFlavorRelease/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="RELEASE_KEY_2" tools:replace="android:value"/>
</application>
</manifest>
manifestMerger 将处理替换,您将在每个场景中得到正确的密钥。我刚刚成功实施了它。我只是希望你真的指的是 Fabric 键! :)
希望对您有所帮助!
与接受的答案类似,如果您不想复制您的清单,您可以使用字符串资源来完成。
例如,如果您有两种口味(口味 1 和口味 2) 您最终会得到以下源集。
app/
src/
main/
res/
values/strings.xml
flavor1Release/
res/
values/strings.xml
flavor1Debug/
res/
values/strings.xml
flavor2Release/
res/
values/strings.xml
flavor2Debug/
res/
values/strings.xml
然后您可以只使用字符串资源作为您的键值
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<meta-data
android:name="io.fabric.ApiKey"
android:value="@string/apiKey" tools:replace="android:value"/>
</application>
</manifest>
将所有密钥保存在一个地方的进一步优化是在主源集中的 strings.xml 中定义它们。然后让 flavor/build 源集引用那些。
例如:
<resources>
<string name="flavor1ReleaseKey">flavor1ReleaseKey</string>
<string name="flavor1DebugKey">flavor1DebugKey</string>
<string name="flavor2ReleaseKey">flavor2ReleaseKey</string>
<string name="flavor2DebugKey">flavor2DebugKey</string>
</resources>
然后在每个 flavor/build sourceSets 中,您只需引用这些键。
flavor1Release/res/values/strings.xml
<resources>
<string name="apiKey">@string/flavor1ReleaseKey</string>
</resources>
您可以通过访问特定 applicationVariant 的 mergedFlavor 在 applicationVariants 中设置 manifestPlaceholders。
android.applicationVariants.all { variant ->
def mergedFlavor = variant.getMergedFlavor()
mergedFlavor.manifestPlaceholders = [appPackageId: "myPackageExample"]
}
如果你使用的是 Kotlin DSL,你应该使用这样的东西:
android.applicationVariants.all { // don't put 'variant ->' here or you'll get the 'all' extension function
// no need to define 'mergedFlavor' because 'this' _is_ the variant so 'mergedFlavor' is already available.
mergedFlavor.manifestPlaceholders = ...
}
我所做的是将当前 AndroidManifest.xml
复制到 app/src/debug
并更改了调试清单中的密钥:
<meta-data
android:name="com.crashlytics.ApiKey"
tools:replace="android:value"
android:value="@string/crashlytics_debug" />
app/src/main
清单就像:
<meta-data
android:name="com.crashlytics.ApiKey"
android:value="@string/crashlytics_live" />
我在 https://azabost.com/android-manifest-placeholders/
中找到了这个很棒的解决方案android {
...
buildTypes {
release {
...
manifestPlaceholders.screenOrientation = "portrait"
}
debug {...}
}
}
或
android {
...
flavorDimensions "features"
productFlavors {
paid {
dimension "features"
manifestPlaceholders.hostName = "www.paid-example.com"
}
free {
dimension "features"
manifestPlaceholders.hostName = "www.free-example.com"
}
}
您不需要重复的文件
Build.gradle
productFlavors {
prod {
applicationId "com.example.prod"
dimension "mode"
manifestPlaceholders = [hostName:"some String"]
}
dev {
applicationId "com.example.dev"
dimension "mode"
manifestPlaceholders = [hostName:"some String"]
}
最明显的使用“${hostName}”。下面的例子
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${hostName}" />
作为@Eric post 的补充,对于 AGP 版本 com.android.tools.build:gradle:4.x
,此代码片段
applicationVariants.all{ variant->
if (variant.productFlavors.get(0).name.equals("someFlavor")) {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_1" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
} else {
if (variant.buildType.name.equals("release")) {
manifestPlaceholders = [ apiKey:"RELEASE_KEY_2" ]
} else {
manifestPlaceholders = [ apiKey:"DEBUG_KEY" ]
}
}
}
应更新为
androidComponents {
onVariants(selector().withBuildType("debug")) {
manifestPlaceholders.apiKey = "DEBUG_KEY"
}
onVariants(selector().withBuildType("release")) {
if(flavorName.equals("someFlavor"))
manifestPlaceholders.apiKey = "RELEASE_KEY_1"
else
manifestPlaceholders.apiKey = "RELEASE_KEY_2"
}
}