87

I'm having issues with defining two different manifest files for my flavors in Android Studio. This is my current project structure:

Current project structure

The AndroidManifest.xml in the free flavor looks like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="se.example.package">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</manifest>

The AndroidManifest.xml in the main flavor has no uses-permissions, but contains the rest of the manifest code that is shared between all flavors.

The AndroidManifest.xml in the pro flavor looks like this:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="se.example.package">
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
</manifest>

build.gradle defines the two flavors like

productFlavors {
    free {
        applicationId 'se.example.package.free'
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 1
        versionName '1.0'
    }
    pro {
        minSdkVersion 14
        applicationId 'se.example.package.pro'
        targetSdkVersion 21
        versionCode 2
        versionName '1.1'
    }
}

The result that I am expecting is that the different flavors defines different uses-permissions. This is not the case. The result is currently that the both flavors only defines the <uses-permission android:name="com.android.vending.CHECK_LICENSE" /> as defined in AndroidManifest.xml in the pro flavor.

I have tried:

  • Clean project
  • Rebuild project
  • Restart Android Studio
  • Sync gradle

But without success. How am I to fix this? Any help is appreciated.

EDIT 1

I changed the location of each flavors AndroidManifest.xml file from each of the res folders to free and pro folder. The result of this:

  1. Pro flavor shows Licence permission as expected.
  2. Free flavor shows permissions from both AndroidManifest.xml files, License and network permissions (Should be only network)

This feels like an issue of project structure. What to make of this?

EDIT 2

I pulled the merge reports as Commonsware hinted, these are the reports regarding uses-permissions

Free:

uses-permission#com.android.vending.CHECK_LICENSE
ADDED from qwknoteGIT:licencing-library:unspecified:26:5
    android:name
        ADDED from qwknoteGIT:licencing-library:unspecified:26:22

Pro:

uses-permission#com.android.vending.CHECK_LICENSE
MERGED from qwknoteGIT:licencing-library:unspecified:26:5
Marcus
  • 6,697
  • 11
  • 46
  • 89
  • I'm not exactly sure on which you have to use (thou it's a comment, not an answer), but you probably can get what u want by using some of the `tools:node` declaration http://tools.android.com/tech-docs/new-build-system/user-guide/manifest-merger#TOC-tools:node-markers – Budius Feb 12 '15 at 13:10
  • "The result is currently that the both flavors only defines the as defined in AndroidManifest.xml in the pro flavor. " -- how have you determined this? – CommonsWare Feb 12 '15 at 13:17
  • @CommonsWare I've both flavors installed on my HTC one x, and when I'm checking permissions for each one they both say "License control for Google Play" (Translated from my phone with Swedish locale, might not be exact translation in English). None of them declare internet permissions. – Marcus Feb 12 '15 at 13:20
  • 1
    Look at the manifest merger report(s) in `app/build/output/apk/` and see what they tell you. – CommonsWare Feb 12 '15 at 13:33
  • "I changed the location of each flavors AndroidManifest.xml file from each of the res folders to free and pro folder" -- that's where they are supposed to be. The manifest goes in the root of the sourceset, whether it is `main`, a flavor's sourceset, or a build type's sourceset. "What to make of this?" -- I repeat my earlier recommendation: Look at the manifest merger report(s) in `app/build/output/apk/` and see what they tell you. – CommonsWare Feb 12 '15 at 13:50
  • I never done permission merging, but again, some of the `tools:node` should. Check the link I posted. Maybe add ALL permissions to the main manifest and remove ones you don't want on each with ` – Budius Feb 12 '15 at 13:52
  • @CommonsWare I've added the report outputs and removed that which did not focus on `uses-permission`s. I'm sorry, but I've never been in contact with this before. I do not know how to interpret them. – Marcus Feb 12 '15 at 14:17
  • @Budius I just tried your solution, and it worked. Please a summary of your comments as an answer. – Marcus Feb 12 '15 at 14:25
  • 1
    Your problem is coming from a library, not your flavors. Specifically, `qwknoteGIT:licencing-library` is requesting `CHECK_LICENSE`. If you are not using that library in all flavors, use a flavored `compile` statement (e.g., `proCompile`) to only use that library in that flavor. – CommonsWare Feb 12 '15 at 15:09
  • @CommonsWare Thank you for your time and efforts Mark. It makes sense now that you've said it. Feel free to post your answer, and I'll upvote it for future answer-seekers. – Marcus Feb 12 '15 at 15:17
  • @Marcus can you check my question as well https://stackoverflow.com/questions/69122776/a-failure-occurred-while-executing-com-android-build-gradle-internal-tasks-worke – Edgar Sep 10 '21 at 08:50

7 Answers7

66

Tech background:

on this link it explains the techniques and parameters that can be use for manifest merging: https://developer.android.com/studio/build/manage-manifests#merge_rule_markers

One in specific is the tools:node that points out how certain XML nodes on the manifest should behave whilst merging.

Solution:

to achieve some permisions in one and different in other manifest, add ALL permissions you need to the main and in the flavours manifest remove the ones you don't need, like the example below:

free remove the check license

<uses-permission
   android:name="com.android.vending.CHECK_LICENSE" 
   tools:node="remove"/>
Budius
  • 39,391
  • 16
  • 102
  • 144
  • 18
    Just one question, instead of adding it in main manifest and removing it from "free" version, why can't we add `android:name="com.android.vending.CHECK_LICENSE"` just to a single "pro" version manifest – Rajkiran Dec 16 '15 at 12:02
25

Your problem is coming from a library, not your flavors. Specifically, qwknoteGIT:licencing-library is requesting CHECK_LICENSE.

If you are not using that library in all flavors, use a flavored compile statement (e.g., proCompile) to only use that library in that flavor.

If you are using the library for all flavors, but feel confident that you do not need the permission in one flavor, that's where a tools:node attribute can be used, in the flavor's manifest, to block out that permission supplied by the library.

And the manifest merger report is your friend. :-)

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks a lot for your efforts, although I can not accept two answers, you provide a good explanation and a working solution. +1 – Marcus Feb 12 '15 at 15:43
  • @Marcus you can change an accepted answer. In my opinion this answer should be accepted. – Ely Jun 24 '18 at 10:03
13

This should solve the problem, at least. I find it useful in specifying the exact manifest to use for each variant. Cheers! It explicitly directs to the manifest file under each variant folder.

    android {
      productFlavors {
        prod {
          manifest.srcFile "prod/AndroidManifest.xml"
        }
        dev {
          manifest.srcFile "dev/AndroidManifest.xml"
        }
      }
      ...

}
Otieno Rowland
  • 2,182
  • 1
  • 26
  • 34
  • 7
    There is no need to specify the path of the `AndroidManifest.xml` files, gradle itself takes them from the flavor folders unless you changed their default path (which I wouldn't recommend). – GoRoS Feb 25 '16 at 07:57
  • 3
    Useful however when still having a maven style project layout – Nicolas Cornette May 09 '16 at 12:55
  • Yes, @GoRos, like I said, this is useful, when you are specifying the exact path. People have various reasons why they would need to do that. – Otieno Rowland Apr 11 '18 at 20:54
  • @OtienoRowland I have tried your answer it did not work maybe you can check my post as well https://stackoverflow.com/questions/69122776/a-failure-occurred-while-executing-com-android-build-gradle-internal-tasks-worke – Edgar Sep 10 '21 at 08:47
5

Specify your Manifest exclusively under sourceSets, In your App build.gradle

 android {
    productFlavors {
                bizdartFlavourNoCallLog {
            minSdkVersion 16
            applicationIdSuffix '.bizdart'
            targetSdkVersion 26
            dimension "tier"
            sourceSets {
                main {
                    manifest.srcFile "src/bizdartFlavourNoCallLog/AndroidManifest.xml"
                }
            }
            copy {
                from 'src/bizdartFlavourNoCallLog/'
                include '*.json'
                into '.'
                }
            }
       }
    }
Ebin Joy
  • 2,690
  • 5
  • 26
  • 39
5

See https://developer.android.com/studio/build/manifest-merge with param tools:node="merge"

High priority manifest (Free):

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:node="merge">
</activity>

Low priority manifest (Main):

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Merged manifest result:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
Alexandr Larin
  • 793
  • 7
  • 13
1

You should change your code:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="se.example.package">

for:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.your.appid">
rocambille
  • 15,398
  • 12
  • 50
  • 68
partizan
  • 285
  • 2
  • 9
0

I encountered the same problem, and I found that it was because I put "pro" and "tree" flavor folder under the lib project, and the problem was solved after I move the flavors folder under the app project

Trinea
  • 649
  • 8
  • 10