I will start by saying that I am very new to Gradle, so I apologize if this has already been answered.
I\'m working on an Android application that uses an API key to
I believe that you need a manifestPlaceHolder to read that value in your Java code, right? If this is the case, you can already read the FLAVOR name in your generated BuildConfig.java. For example, if you define a flavor whose name is smartphone you can access that value using BuildConfig.FLAVOR String; then in your code you can use a simple if (BuildConfig.FLAVOR.equals("smartphone"))...
But maybe you need to read a sort of configuration of your app, an apiKey. In that case, the best way to go is to create a Class or a string resource for every flavor; this is the link for you.
Similarly to the accepted answer, you could do it with string resources, if you didn't want to duplicate your manifests.
For example, if you had two flavors (flavor1 and flavor2) You'd end up w/ the following source sets.
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
You could then just use a string resource for your key value
<?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>
One further optimization to keep all your keys in one place is to define them all in strings.xml in your main source set. and then have the flavor/build source sets reference those.
for example:
<resources>
<string name="flavor1ReleaseKey">flavor1ReleaseKey</string>
<string name="flavor1DebugKey">flavor1DebugKey</string>
<string name="flavor2ReleaseKey">flavor2ReleaseKey</string>
<string name="flavor2DebugKey">flavor2DebugKey</string>
</resources>
then in each of your flavor/build sourceSets, you just reference those keys.
flavor1Release/res/values/strings.xml
<resources>
<string name="apiKey">@string/flavor1ReleaseKey</string>
</resources>
You may set manifestPlaceholders inside applicationVariants by accessing mergedFlavor for specific applicationVariant.
android.applicationVariants.all { variant ->
def mergedFlavor = variant.getMergedFlavor()
mergedFlavor.manifestPlaceholders = [appPackageId: "myPackageExample"]
}
I found this great solution in https://azabost.com/android-manifest-placeholders/
android {
...
buildTypes {
release {
...
manifestPlaceholders.screenOrientation = "portrait"
}
debug {...}
}
}
or
android {
...
flavorDimensions "features"
productFlavors {
paid {
dimension "features"
manifestPlaceholders.hostName = "www.paid-example.com"
}
free {
dimension "features"
manifestPlaceholders.hostName = "www.free-example.com"
}
}
What i did is copied current AndroidManifest.xml
into app/src/debug
and changed the key there debug Manifest :
<meta-data
android:name="com.crashlytics.ApiKey"
tools:replace="android:value"
android:value="@string/crashlytics_debug" />
app/src/main
Manifest is like :
<meta-data
android:name="com.crashlytics.ApiKey"
android:value="@string/crashlytics_live" />
I would guess that you are referring to Fabric ApiKey? :) I just spent hours trying to do it in a similar way with the placeholders and specifying the ApiKey in the gradle file although it does not seem possible as of com.android.tools.build:gradle:1.3.1
. It is possible to specify a placeholder for a specific flavor but not for a flavor AND buildType.
Just to correct your syntax, the way you would have to do it (if it was possible) would be something like that but manifestPlaceholders are unknown to variants.
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" ]
}
}
}
What you actually need to do is to keep the key in the AndroidManifest.xml
and handle it with multiple manifest file
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>
The manifestMerger will handle the replacement and you will end up with the proper key in every scenario. I just implemented it successfully. I just hope you were really referring to the Fabric key! :)
Hope this helps!