Android Studio two flavors with different manifest files
I'm having issues with defining two different manifest files for my flavors in Android Studio. This is my 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:
- Pro flavor shows Licence permission as expected.
- 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
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"/>
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. :-)
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"
}
}
...
}
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 '.'
}
}
}
}
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>