How do I change the AndroidManifest.xml file based on build variants?
Asked Answered
F

4

15

I have an app with multiple build variants. The variants are used to build versions of the same app for different companies. So, I have several different variants that build different apps:

  • com.acme.app1
  • com.schmoe.app2
  • com.yop.app3
  • etc...

The build.gradle file handles this very well:

     productFlavors {
    app1 {
        applicationId "com.acme.app1"
    }

    app2 {
        applicationId "com.schmoe.app2"
    }

    app3 {
        applicationId "com.yop.app3"
    }

}

Here's my problem. I am integrating Dropbox into my apps. The AndroidManifest.xml file must be changed for each variant to include the appropriate app key (stored in my string file). Dropbox has the following addition to the manifest file:

         <activity
        android:name="com.dropbox.client2.android.AuthActivity"
        android:launchMode="singleTask"
        android:configChanges="orientation|keyboard">

        <intent-filter>
            <!-- Change this to be db- followed by your app key -->
            <data android:scheme="db-abcdef" />
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE"/>
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

Each build variant needs to change the following line:

 <data android:scheme="db-abcdef" />

to the appropriate value for each app variant. In other words, I need to replace part of the above string based on the build variant. For instance

App1

 <data android:scheme="db-111111" />

App2

 <data android:scheme="db-222222" />

App3

 <data android:scheme="db-333333" />

The line is the same for each variant up to the text "db-".

What I need is to dynamically replace the variable portion of the string (the x values) "db-xxxxxx" with a string from my string file.

I think this can be done with gradle scripts but I'm a complete newb with gradle. HELP!

If you can help, please be very specific about what goes where since I SUCK at gradle files and scripting. Thanks in advance!

Fructificative answered 21/1, 2015 at 21:26 Comment(0)
C
7

You can do this the same way you would modify the app name, using a string resource. In your manifest, include:

<data android:scheme="@string/db_scheme" />

Next, you add resources folders for the various build types, and in each, place a custom copy of a resource file, say res/values/flavor.xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
    <string name="app_name">Customer 1 App</string>
    <string name="db_scheme">db-111111</string>
</resources>

This will allow you to have different API keys, schemes, app-names, icons, etc. for your various flavors.

Carnallite answered 21/1, 2015 at 21:40 Comment(2)
Is there a way to concatenate the strings? The string in the string file is just the portion after db-. Translated: Let's say the app key is 123456. The string entry is "123456". I need to concatenate that with "db-" and make "db-123456". Obviously, I could store it with db- and then parse that off before calling the api, but, I was just curious.Fructificative
I'm having a problem. The string loaded in my app is loading the right key. But the key loaded in the manifest file is loading the string from the main variant and NOT the variant that I'm compiling. Is there a way to instruct the manifest to load the correct variant string file?Fructificative
G
21

You can save the string in build.gradle too:

productFlavors {
    app1 {
        applicationId "com.acme.app1"
        resValue "string", "my_app_key", "db-abc"
    }

    app2 {
        applicationId "com.schmoe.app2"
        resValue "string", "my_app_key", "db-def"
    }

    app3 {
        applicationId "com.yop.app3"
        resValue "string", "my_app_key", "db-ghi"
    }
}

And then use it like:

<data android:scheme="@string/my_app_key" />
Gilbertine answered 21/1, 2015 at 21:49 Comment(1)
This works. I'll give this an up vote but the answer from 323go is closer to what I need. It doesn't require me to have the value in 2 places. Thanks for the help. This will help me with a couple of other things I looking for.Fructificative
C
7

You can do this the same way you would modify the app name, using a string resource. In your manifest, include:

<data android:scheme="@string/db_scheme" />

Next, you add resources folders for the various build types, and in each, place a custom copy of a resource file, say res/values/flavor.xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
    <string name="app_name">Customer 1 App</string>
    <string name="db_scheme">db-111111</string>
</resources>

This will allow you to have different API keys, schemes, app-names, icons, etc. for your various flavors.

Carnallite answered 21/1, 2015 at 21:40 Comment(2)
Is there a way to concatenate the strings? The string in the string file is just the portion after db-. Translated: Let's say the app key is 123456. The string entry is "123456". I need to concatenate that with "db-" and make "db-123456". Obviously, I could store it with db- and then parse that off before calling the api, but, I was just curious.Fructificative
I'm having a problem. The string loaded in my app is loading the right key. But the key loaded in the manifest file is loading the string from the main variant and NOT the variant that I'm compiling. Is there a way to instruct the manifest to load the correct variant string file?Fructificative
W
3

For people visiting this in 2019: You can use manifestPlaceholders per flavor. In your case:

productFlavors {
  app1 {
      applicationId "com.acme.app1"
      manifestPlaceholders.scheme = "db-111111"
  }

  app2 {
      applicationId "com.schmoe.app2"
      manifestPlaceholders.scheme = "db-222222"
  }

  app3 {
      applicationId "com.yop.app3"
      manifestPlaceholders.scheme = "db-333333"
  }
}

and then use it in your manifest:

<activity
    android:name="com.dropbox.client2.android.AuthActivity"
    android:launchMode="singleTask"
    android:configChanges="orientation|keyboard">

    <intent-filter>
        <!-- Change this to be db- followed by your app key -->
        <data android:scheme="${scheme}" />
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
Waterspout answered 29/7, 2019 at 13:6 Comment(1)
There is more simple way - you can put separate AndroidManifest.xml into each build variant's directory and include only differences, all remaining fields should be loaded from main AndroidManifestStrasser
R
1

Yet another way that is somewhat similar to Hibbem's answer:

android {
    defaultConfig {
        manifestPlaceholders = [schemeName: "default-scheme"]
    }
    ...
    app1 {
      applicationId "com.acme.app1"
      manifestPlaceholders = [schemeName: "db-111111"]
    }
    ...
}

And in your manifest:

<intent-filter>
    ...
    <data android:scheme="${schemeName}" />
    ...
</intent-filter>

More from the official docs

Robbert answered 29/11, 2019 at 20:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.