I would like to set an android permission's protectionLevel dynamically depending on debug or release, say, from the build.gradle file, something like this:
The AndroidManifest.xml file:
<permission
android:name="com.somestring.MY_CUSTOM_PERMISSION"
android:protectionLevel=BuildConfig.protectionlevel />
And the build.gradle file:
android {
buildTypes {
release {
buildConfigField "String" , "protectionlevel" , "signature"
}
debug{
buildConfigField "String" , "protectionlevel" , "normal"
}
}
}
Setting variables from build.gradle in this way works in java / other cases, but does not work for signature. I have tried some other variations that you can find in a quick Google search, but so far, I could not make it work for this case.
Usually manifest placeholders can be used:
buildTypes {
release {
manifestPlaceholders = [protectionLevel: "signature"]
}
debug{
manifestPlaceholders = [protectionLevel: "normal"]
}
}
And then:
<permission
android:name="com.somestring.MY_CUSTOM_PERMISSION"
android:protectionLevel="${protectionLevel}" />
Related
In my AndroidManifest.xml file I have the following line:
<supports-gl-texture android:name="${supportedTexture}" />
I inject the correct supported texture in gradle file based on the selected flavor, for example like this:
productFlavors {
ETC1 {
manifestPlaceholders = [supportedTexture: "GL_OES_compressed_ETC1_RGB8_texture"]
}
}
However, this doesn't work if I want to add several supports-gl-texture lines in the manifest. So how should I edit AndroidManifest.xml and build.gradle file if I'd like to have multiple supportedTextures like this:
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_AMD_compressed_ATC_texture" />
Would it be possible to do something like this in gradle file:
productFlavors {
ETC1 {
manifestPlaceholders = [supportedTexture: "GL_OES_compressed_ETC1_RGB8_texture"]
}
ETC1andATC {
//manifestPlaceHolders = ???
}
}
Or is my only option to go outside gradle and have for example multiple Manifest files which I copy to project depending on gradle flavor?
If you have limited numbers of supported textures then you can define multiple keys for all those textures and use in the manifest file.
productFlavors {
ETC1 {
manifestPlaceholders = [
supportedTexture1: "GL_OES_compressed_ETC1_RGB8_texture",
supportedTexture2: "GL_AMD_compressed_ATC_texture"]
}
}
Then in your manifest
<supports-gl-texture android:name="${supportedTexture1}" />
<supports-gl-texture android:name="${supportedTexture2}" />
I am trying to configure some SDK inside application and I am facing this gradle problem, that just gives me a headache. What I have to do is set below value
manifestPlaceholders = [manifestApplicationId: "$applicationId"]
to be something like com.flavorA.debug for debug builds and honestly I have no idea how am I supposed to set this. If I put this section to defaultConfig then I get null inside my manifest file. If I put it to productFlavors section then I only get com.flavorA, so I'm missing buildType suffix.
I was also trying different things like
applicationVariants.each{ variant->
manifestPlaceholders = [manifestApplicationId: "test"]
}
but above doesn't even change the name to test, not mentioning other things.
How am I supposed to solve this with gradle?
You don't need manifestPlaceHolders or the applicationVariants block to achieve this. The applicationId and the package name in the manifest is decoupled, so you simply write:
productFlavors {
pro {
applicationId = "com.example.my.pkg.pro"
}
free {
applicationId = "com.example.my.pkg.free"
}
}
and if you want to change it for the build type:
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
More details here:
applicationid-vs-packagename
I am very hyped about the new possibility of manifest placeholders in Gradle + Android Build. I've found in the gradle documentation that I can specify my own placeholders like this:
productFlavors {
free {
}
pro {
manifestPlaceholders = [ activityLabel:"proName" ]
}
}
But I would like to have one placeholder dependent on build type and not on product flavors. When I insert that placeholder specification into build type settings it takes no effect. Do you know how to achieve this? Because it seems to me stupid have three build types and three flavors associated with it. Thanks
This is my solution for different product flavours:
build.gradle:
productFlavors {
normal {
applicationId "mobi.cwiklinski.urc"
buildConfigField "String", "providerAuthority", "\"mobi.cwiklinski.urc.provider\""
resValue "string", "authorities", "mobi.cwiklinski.urc.provider"
}
adfree {
applicationId "mobi.cwiklinski.urc.adfree"
buildConfigField "String", "providerAuthority", "\"mobi.cwiklinski.urc.adfree.provider\""
resValue "string", "authorities", "mobi.cwiklinski.urc.adfree.provider"
}
}
AndroidManifest.xml
<provider
android:name="mobi.cwiklinski.urc.provider.AppProvider"
android:authorities="#string/authorities"
android:exported="true"
android:label="#string/app_name"
android:syncable="true"
android:writePermission="mobi.cwiklinski.urc.permission.USE_PROVIDER" />
And that's all - in different product flavours you will get different resource value.
Starting today with gradle plugin 0.13.0 is already working.
I have two build types set in my gradle file: debug and release. I'd like to be able to set a different app icon for the debug build type. Is there any way to this just through the build type, without getting into product flavors? build.gradle file is below.
apply plugin: 'android'
//...
android {
compileSdkVersion 19
buildToolsVersion "19.0.3"
defaultConfig {
minSdkVersion 14
targetSdkVersion 19
versionCode 30
versionName "2.0"
}
buildTypes {
debug {
packageNameSuffix '.debug'
versionNameSuffix '-SNAPSHOT'
}
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
Figured it out. What you need to do is create a separate src folder called debug that holds the different icons. For example, if your project layout is as follows, and your launcher icon is called ic_launcher.png:
[Project Root]
-[Module]
-src
-main
-res
-drawable-*
-ic_launcher.png
Then to add a separate icon for the debug build type, you add:
[Project Root]
-[Module]
-src
-main
-res
-drawable-*
-ic_launcher.png
-debug
-res
-drawable-*
-ic_launcher.png
Then, when you build under the debug build type, it will use the ic_launcher found in the debug folder.
This is a handy approach although it has an important downside... both launchers will be put into your apk. – Bartek Lipinski
The better way: InsanityOnABun's answer
AndroidManifest.xml
<manifest
...
<application
android:allowBackup="true"
android:icon="${appIcon}"
android:roundIcon="${appIconRound}"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
...
</application>
</manifest>
build.gradle
android {
...
productFlavors{
Test{
versionName "$defaultConfig.versionName" + ".test"
resValue "string", "app_name", "App-Test"
manifestPlaceholders = [
appIcon: "#mipmap/ic_launcher_test",
appIconRound: "#mipmap/ic_launcher_test_round"
]
}
Product{
resValue "string", "app_name", "App"
manifestPlaceholders = [
appIcon: "#mipmap/ic_launcher",
appIconRound: "#mipmap/ic_launcher_round"
]
}
}
}
the Github url:Build multi-version App with Gradle
You can specify the icon in the product flavor's partial AndroidManifest.xml file as well:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
tools:replace="android:icon"
android:icon="#drawable/alternative_icon" />
</manifest>
This will overwrite the icon that you specify in the original AndroidManifest.xml
For getting different icons while using different flavors with multiple dimensions, such as:
flavorDimensions "color", "size"
productFlavors {
black {
dimension "color"
}
white {
dimension "color"
}
big {
dimension "size"
}
small {
dimension "size"
}
}
This can be achieved as:
First, put the debug resources in separate folders, such as:
src/blackDebug/res
src/whiteDebug/res
Second, put the key with multiple flavor dimensions is that the sourceset name must contain all the possible flavor combinations, even if some of these dimensions do not affect the icon.
sourceSets {
// Override the icons in debug mode
blackBigDebug.res.srcDir 'src/blackDebug/res'
blackSmallDebug.res.srcDir 'src/blackDebug/res'
whiteBigDebug.res.srcDir 'src/whiteDebug/res'
whiteSamllDebug.res.srcDir 'src/whiteDebug/res'
}
Just to make it clear, the following will not work when multiple dimensions are in use:
sourceSets {
// Override the icons in debug mode
blackDebug.res.srcDir 'src/blackDebug/res'
whiteDebug.res.srcDir 'src/whiteDebug/res'
}
Step by step solution, including replacing mipmap-anydpi-v26 and keeping files for all dimensions:
First define in build.gradle (Module: app) your build type in android -> buildTypes -> debug, internal, etc
On the project hierarchy, below Android, right click on app -> New -> Image Asset -> in Path choose your icon -> any other changes on Background Layer and Legacy -> Next -> in Res Directory choose your desired build type (debug, internal, main, etc) -> Finish
That way the icons will replace every old icon you had.
Before i build android project to two different application paid and free.
I changed each values and strings so yesterday I made a big mistake.
So, I'm laerning how to use gradle to build my app.
My app have some differents.
app name (just add suffix '-Free') -> values/string.xml
change flag in my *.java
// signingConfigs is ommited.
productFlavors{
free{
packageName "my.app.free"
versionCode 20
signingConfig signingConfigs.freeConfing
copy{
from('/res'){
include '**/*.xml'
}
into 'build/res/'
filter{
String line -> line.replaceAll("android:label=\"#string/app_name\"", "android:label=\"#string/app_name_free\"")
}
}
copy{
from('/src'){
include '**/*.java'
}
into 'build/src/'
filter{
String line -> line.replaceAll("public static final Boolean IS_FULL_VER = true;", "public static final Boolean IS_FULL_VER = false;")
}
}
}
paid{
packageName "my.app.paid"
versionCode 20
signingConfig signingConfigs.paidConfing
}
}
but, built app changed nothing at all.
What i missed?
See the documentation on product flavors:
http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors
In your build.gradle, in each flavor, you can define flags to be generated in your BuildConfig.java file:
productFlavors {
free {
packageName "com.company.appfree"
buildConfig "public final static com.company.common.MonetizationType monetizationType = com.company.common.MonetizationType.FREE;"
}
paid {
packageName "com.company.apppaid"
buildConfig "public final static com.company.common.MonetizationType monetizationType = com.company.common.MonetizationType.PAID;"
}
}
This example uses an enum (that you need to define somewhere in your java code):
public enum MonetizationType {
PAID, FREE
}
You can now use this anywhere like this:
if (BuildConfig.monetizationType == MonetizationType.FREE) { ... }
For overriding resources, you can create different resource files in the source folders for each flavor:
Use the following structure
app/build.gradle
app/ [.. some other files...]
app/src/main/
app/src/main/java
app/src/main/res
app/src/main/assets
app/src/main/AndroidManifest.xml
app/src/free/res/values/apptitle.xml
app/src/paid/res/values/apptitle.xml
apptitle.xml would be a string resource file (just like strings.xml), but with only one string: the one you want to be different depending on the flavor.
(You don't need have a apptitle.xml in your main/res directory).
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_title">App Title (or whatever you want)</string>
</resources>
You might be able to override strings in different ways, but I like to keep the overridden strings separate from the rest for clarity.
The accepted answer is not working with the newer versions of Gradle.
You need to replace buildConfig with buildConfigField to get the same result:
productFlavors {
free {
packageName "com.company.appfree"
buildConfigField "com.company.common.MonetizationType", "MONETIZATION_TYPE", "company.common.MonetizationType.FREE"
}
paid {
packageName "com.company.apppaid"
buildConfigField "com.company.common.MonetizationType", "MONETIZATION_TYPE", "company.common.MonetizationType.PAID"
}
}
treesAreEverywhere's answer (as well as user name) is right on. But it's also very valuable to know that Android Studio will greatly simplify the process of creating build flavor or attribute specific resource files.
In the AS project window, right click on the res/values folder and select New > Values resource file. Then name it (e.g., "strings"), select the Source set if not the default, and select any desired qualifiers (e.g., Screen Width = 800). This is the easiest way to make sure you're putting your resource overrides where the compiler wants them.
This is how I did in my project. I created multiple build types instead of flavours. This solution will add a prefix to your package name based on what build type you are trying to assemble. For ex, for dev the package name will be com.sample.myapp.dev and similarly for beta package name will be changed to com.sample.myapp.release. You can tweak it to get Free and Paid prefixes. Hope it would help.
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.production
applicationIdSuffix '.release'
versionNameSuffix '-RELEASE'
}
dev {
signingConfig signingConfigs.debug
applicationIdSuffix '.dev'
versionNameSuffix '-DEV'
}
beta {
signingConfig signingConfigs.debug
applicationIdSuffix '.beta'
versionNameSuffix '-BETA'
}
debug {
signingConfig signingConfigs.debug
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
debuggable true
}
}