custom strings for debug buildType - android

I have an android app and I want to change the app label for the debug and other buildTypes. I don´t have any flavors!
Here is the setup that I believe looks like it should work:
-src
|-debug
|-res
|-values
|-strings.xml
|-main
|-res
|-values
|-strings.xml
|-java
[...]
I have no custom sourcesets just a debug buildType:
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
so I though
sourceSets.debug.res.srcDirs = ['src/debug/res']
would to the trick. But it doesn't. Any ideas?
How to change app name per Gradle build type does not work anymore...

I found another sweet solution to this, using manifest placeholders:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="${applicationLabel}">
<activity
android:label="${applicationLabel}">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
and in your gradle file:
android {
defaultConfig {
manifestPlaceholders = [ applicationLabel:"#string/app_name"]
}
buildTypes {
debug {
applicationIdSuffix ".debug"
manifestPlaceholders = [ applicationLabel:"MyApp Debug"]
}
}
}

buildTypes {
release {
resValue 'string', 'APP_NAME', '"My App Release"'
}
debug {
resValue 'string', 'APP_NAME', '"My App Debug"'
}
}
value\strings.xml
< string name="app_name" >#string/APP_NAME< /string>
and use app_name everywhere

You have to use
|-debug
|-res
|-values
|-strings.xml
In your picture you have debug/res/strings.xml
Also you doens't need it (because it is the standard, but the issue isn't here).
sourceSets.debug.res.srcDirs = ['src/debug/res']

Forget the string.xml files. All can be easily configured in build.gradle.
First of all, you should maintain the string pointer "app_name" in AndroidManifest file, and delete all instances of "app_name" in string's resource files:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="#string/app_name">
<activity
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Secondly, the resource value of #string/app_name is currently not defined. So we must apply its default definition in build.gradle:
defaultConfig {
applicationId "com.example.myapp"
minSdkVersion 14
targetSdkVersion 22
versionCode 123423432
versionName "1.0.0"
resValue 'string', 'app_name', '"My app label"'
}
Currently, app_name is defined for all build types. By assuming you want to change the app label for the buildTypes, each build type must be defined with a string value in the same build.gradle branch:
buildTypes {
release {
resValue 'string', 'app_name', '"My app label Release"'
}
debug {
resValue 'string', 'app_name', '"My app label Debug"'
}
}
Since this resource value is set programmatically, we also need to add a certain translations lint ignore in case of a Release build:
lintOptions { disable 'MissingTranslation' }
In case you want to change it accordingly with a set of defined Flavours(dev, qua or prd) add the resValues definitions in productFlavours instead of buildTypes:
productFlavors {
dev {
applicationId "com.example.myapp.dev"
resValue 'string', 'app_name', '"My app label Dev"'
}
qua {
applicationId "com.example.myapp.qua"
resValue 'string', 'app_name', '"My app label Qua"'
}
prd {
applicationId "com.example.myapp.prd"
resValue 'string', 'app_name', '"My app label Prd"'
}
}

You can create a string in gradle that will be available in xml too:
buildTypes {
debug {
buildConfigField "String", "app_name", "AppDebug"
}
release {
buildConfigField "String", "app_name", "AppRelease"
}
And then use it in xml:
android:label="#string/app_name"
Just make sure app_name not specified in your strings.xml.

Try this.
buildTypes {
debug {
applicationIdSuffix ".debug"
}
sourceSets.debug.resources.srcDirs = ['src/debug/res']
}

Have you remembered to get rid of the directory listing inside your app's build.gradle?
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDir 'src'
// res.srcDir 'res' <--- This line should be removed
assets.srcDir 'assets'

I know this is quite an old question, but I've had the same problem and just solved it.
You should update these codes if you have one in your build.gradle for your app.
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
These codes automatically generate your AppName.iml and set default debug and release directory to /build-types/debug/res, which is different from src/debug/res.

Related

Branch IO Android SDK initialization error

I try to setup Branch.io on android, but get an error:
BranchSDK: Warning: Please enter your branch_key in your project's
res/values/strings.xml!
Manifest:
<!-- Branch init -->
<meta-data android:name="io.branch.sdk.BranchKey" android:value="#string/branch_key" />
<!-- Branch testing (TestMode "true" to simulate fresh installs on dev environment) -->
<meta-data android:name="io.branch.sdk.TestMode" android:value="#bool/branch_io_test_mode" />
<!-- Branch install referrer tracking -->
<receiver android:name="io.branch.referral.InstallListener" android:exported="#bool/branch_io_test_mode">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
Gradle:
buildTypes {
debug {
resValue "bool", "branch_io_test_mode", "true"
resValue 'string', 'branch_key', '"key_live_*"'
...
}
release {
resValue "bool", "branch_io_test_mode", "false"
resValue 'string', 'branch_key', '"key_live_*"'
....
}
Application onCreate:
if (BuildConfig.DEBUG) {
Branch.enableDebugMode();
}
Branch.disableLogging();
Branch.getAutoInstance(this);
What exactly I am doing wrong? To be sure, there is no info about branch_key should be in strings on SDK setup page.
So a fed days after I got my fault.
Depending on build I neither set io.branch.sdk.TestMode to true or false. So when app compiled with TestMode true, Branch looked for Test key but not production key.
So actually my gradle shoud looks like:
buildTypes {
debug {
resValue "bool", "branch_io_test_mode", "true"
resValue 'string', 'branch_key', '"key_test_*"'
...
}
release {
resValue "bool", "branch_io_test_mode", "false"
resValue 'string', 'branch_key', '"key_live_*"'
....
}

Android Gradle: Install all build types on one device

How do I configure my project to be able to install the debug version alongside the release version when using GCM, ContentProvider, AccountType? (without the use of flavors)
I keep getting errors such as: INSTALL_FAILED_CONFLICTING_PROVIDER or INSTALL_FAILED_DUPLICATE_PERMISSION
Installing a debug apk and the release apk on the same device is tricky if you are only using build types and not flavors (Why Build types and not flavors)
Most blog post are either outdated (talking about packageName) or force you to use flavors because the solution they propose does not support applicationIdSuffix and a build type cannot declare applicationId therefore you need to use a flavors
The solution I propose uses
an authority per build type
an account type per build type
a GCM permission per build type
For this to work I use applicationIdSuffix, manifest placeholders, BuildConfigField and resValue in the Gradle file.
The only problem left is when you want to have a different name for app and per language the string is not set as translatable (bug aosp tracker)
This forces you to set abortOnError false otherwise you won't be able to make a release build.
build.gradle
project.ext {
defaultApplicationId = "com.myapp.package"
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId defaultApplicationId
manifestPlaceholders = [ applicationIdWithSuffix: "${applicationId}" ]
buildConfigField "String", "ACCOUNT_TYPE", "\"${applicationId}\""
buildConfigField "String", "AUTHORITY", "\"${applicationId}.provider\""
resValue "string", "account_type", "${applicationId}"
resValue "string", "authority", "${applicationId}.provider"
}
buildTypes {
debug {
applicationIdSuffix ".debug"
debuggable true
manifestPlaceholders = [ applicationIdWithSuffix: defaultApplicationId + ".debug" ]
buildConfigField "String", "ACCOUNT_TYPE", "\"${defaultApplicationId}.debug\""
buildConfigField "String", "AUTHORITY", "\"${defaultApplicationId}.debug.provider\""
resValue "string", "account_type", "${defaultApplicationId}.debug"
resValue "string", "authority", "${defaultApplicationId}.debug.provider"
}
}
lintOptions {
abortOnError false
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mypackage" >
<permission
android:name="${applicationIdWithSuffix}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationIdWithSuffix}.permission.C2D_MESSAGE" />
<application
android:label="#string/app_name" >
<provider
android:name=".MyContentProvider"
android:authorities="${applicationIdWithSuffix}.provider"
android:exported="false"
android:multiprocess="true" />
</application>
</manifest>
Sync adapter xml
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="#string/authority"
android:accountType="#string/account_type"/>
Account authenticator
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="#string/account_type"
.../>
ContentProvider
I have a constant for Authority which takes it from the BuildConfig.
AUTHORITY = BuildConfig.AUTHORITY
Account type
To get the account type you take it from the BuildConfig too.
BuildConfig.ACCOUNT_TYPE
Multi language app name
If you want different names per app & language:
debug/values-en/strings.xml
<resources>
<string name="app_name">MyApp debug EN</string>
</resources>
debug/values-fr/strings.xml
<resources>
<string name="app_name">MyApp debug FR</string>
</resources>
main/values-en/strings.xml
<resources>
<string name="app_name">MyApp EN</string>
</resources>
main/values-fr/strings.xml
<resources>
<string name="app_name">MyApp FR</string>
</resources>

How to refer to a String var defined in build.gradle?

I hope to display different app name based free and pro version.
I define buildConfigField "String", "AppName", "\"Message Cleanup\"" in build.gradle, but I don't know how to apply to android:label in AndroidManifest.xml.
Could you help me ? Thanks!
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.dodata.messagecleanup" >
<application
android:allowBackup="true"
android:icon="#mipmap/clenupmessage"
android:label="AppName"
android:theme="#style/AppTheme" >
<activity android:name="ui.CleanupDelete"
android:label="AppName">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "info.dodata.messagecleanup"
minSdkVersion 9
targetSdkVersion 22
versionCode 7
versionName "1.07"
archivesBaseName = "MessageCleanup-V" + versionName
}
productFlavors {
free {
applicationId "info.dodata.messagecleanup"
buildConfigField "String", "AppName", "\"Message Cleanup\""
}
pro {
applicationId "info.dodata.messagecleanup.pro"
buildConfigField "String", "AppName", "\"Message Cleanup Pro\""
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'com.google.android.gms:play-services:7.3.0'
}
To kcoppock
The manifestPlaceholders can do that.
productFlavors {
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
baidu {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "New"]
}
c360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "c360"]
}
uc {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "uc"]
}
}
In AndroidManifest.xml, I can use it as the following code
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
Assuming you are using the standard project structure (e.g. you have something like src/main/res/values/strings.xml), create additional directories for each flavor:
src/free/res/values/strings.xml
src/pro/res/values/strings.xml
And define the same string key (e.g. app_name) in both of those files, with the correct value for each variant. So you'd have something like:
src/free/res/values/strings.xml
<string name="app_name">Message Cleanup</string>
src/pro/res/values/strings.xml
<string name="app_name">Message Cleanup Pro</string>
The resource merger will merge in these strings based on which variant is being built. Now you can just refer to the app_name string in code, and know that it'll render correctly based on the currently built flavor.

How to change app name per Gradle build type

I am trying to figure out a way to be able to change my application's app name per build type in gradle.
For instance, I would like the debug version to have <APP_NAME>-debug and the qa version to have <APP-NAME>-QA.
I am familiar with:
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
}
However, I can't seem to find a gradle command to apply the change of the app when in the launcher.
If by "app name", you mean android:label on <application>, the simplest solution is to have that point at a string resource (e.g., android:label="#string/app_name"), then have a different version of that string resource in a src/debug/ sourceset.
You can see that in this sample project, where I have a replacement for app_name in src/debug/res/values/strings.xml, which will be applied for debug builds. release builds will use the version of app_name in src/main/.
You can use something like this
buildTypes {
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
resValue "string", "app_name", "AppName debug"
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
zipAlignEnabled true
resValue "string", "app_name", "AppName"
}
}
You can use #string/app_name in AndroidManifest.xml files.
Make sure you remove app_name from values/ folder (no entry by this name).
You can do this with gradle:
android {
buildTypes {
release {
manifestPlaceholders = [appName: "My Standard App Name"]
}
debug {
manifestPlaceholders = [appName: "Debug"]
}
}
}
Then in your AndroidManifest.xml put:
<application
android:label="${appName}"/>
<activity
android:label="${appName}">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Note: it also works with productFlavors.
To support translations make this:
1. remove string "app_name"
2. add to gradle
buildTypes {
admin {
resValue "string", "app_name", "#string/app_name_admin"
}
release {
resValue "string", "app_name", "#string/app_name_release"
}
debug {
resValue "string", "app_name", "#string/app_name_debug"
}
}
3. Set app name in Manifest as "#string/app_name"
4. Add to strings.xml values
<string name="app_name_admin">App Admin</string>
<string name="app_name_release">App release</string>
<string name="app_name_debug">App debug</string>
The app name is user-visible, and that's why Google encourages you to keep it in your strings.xml file. You can define a separate string resource file that contains strings that are specific to your buildTypes. It sounds like you might have a custom qa buildType. If that's not true, ignore the qa part below.
└── src
├── debug
│   └── res
│   └── buildtype_strings.xml
├── release
│   └── res
│   └── buildtype_strings.xml
└── qa
   └── res
   └── buildtype_strings.xml
We need a solution to support app name with localization (for multi language).
I have tested with #Nick Unuchek solution, but building is failed (not found #string/) . a little bit change to fix this bug:
build.gradle file:
android {
ext{
APP_NAME = "#string/app_name_default"
APP_NAME_DEV = "#string/app_name_dev"
}
productFlavors{
prod{
manifestPlaceholders = [ applicationLabel: APP_NAME]
}
dev{
manifestPlaceholders = [ applicationLabel: APP_NAME_DEV ]
}
}
values\strings.xml:
<resources>
<string name="app_name_default">AAA prod</string>
<string name="app_name_dev">AAA dev</string>
</resources>
values-en\strings.xml:
<resources>
<string name="app_name_default">AAA prod en</string>
<string name="app_name_dev">AAA dev en</string>
</resources>
Manifest.xml:
<application
android:label="${applicationLabel}" >
</application>
For a more dynamic gradle based solution (e.g. set a base Application name in main's strings.xml once, and avoid repeating yourself in each flavor / build type combination's strings.xml), see my answer here: https://stackoverflow.com/a/32220436/1128600
There are multiple ways you can do.
you can create manifestPlaceholders OR resValue in app level build.gradle. e.g.
buildTypes {
release {
...
manifestPlaceholders = [appLabel: "My App"]
//resValue "string", "appLabel", '"My App"'
}
debug {
...
manifestPlaceholders = [appLabel: "My App - Debug"]
//resValue "string", "appLabel", '"My App - Debug"'
}
}
OR
If you have productFlavors, you can create there
flavorDimensions "env"
productFlavors {
dev {
dimension "env"
...
manifestPlaceholders = [appLabel: "My App - Development"]
//resValue "string", "appLabel", '"My App - Development"'
}
prod {
dimension "env"
...
manifestPlaceholders = [appLabel: "My Awesome App"]
//resValue "string", "appLabel", '"My Awesome App"'
}
}
Then in AndroidManifest.xml if you are using manifestPlaceholders, just change android:label="${appLabel}" as below OR if you are using resValue, just change android:label=#string/appLabel
<application
...
android:label="${appLabel}"> //OR `android:label=#string/appLabel`
<activity
...
android:label="${appLable}">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
NOTE: Make sure to change android:lable as well in <activity> of LAUNCHER category. If it doesn't require to use android:label in <activity>, just remove this.
If you do not want to add in build.gradle directly, you can add in values/string.xml of selected ProductFlavors. e.g.
Add
<string name="appLabel">My App - Development</string>
in app/src/dev/res/values/string.xml
and
<string name="appLabel">My Awesome App</string>
in app/src/prod/res/values/string.xml
You can use strings.xml in different folders, see Android separate string values for release and debug builds.
So, create this file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Your app name</string>
</resources>
Then paste it to app\src\debug\res\values\ and app\src\release\res\values\ folders. Replace "Your app name" in debug and release files. Remove app_name item from strings.xml in app\src\main\res\values\ folder.
In AndroidManifest you will have the same
<application
android:label="#string/app_name"
...
No changes at all. Even if you added a library with it's AndroidManifest file and strings.xml.
As author asks to do this in Gradle, we can assume he want to do it in the script and not in the configuration files. Since both Android Studio and Gradle has been heavily updated and modified in the last year (~2018) all other answers above, seem overly contorted. The easy-peasy way, is to add the following to your app/build.gradle:
android {
...
buildTypes {
...
// Rename/Set default APK name prefix (app*.apk --> AwesomeApp*.apk)
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
def appName = "AwesomeApp"
outputFileName = appName+"-${output.baseName}-${variant.versionName}.apk"
}
}
}

Use package name in XML

I'm using Android Studio to build my application. I would like to use gradle buildTypes. I add a suffix to the package name with applicationIdSuffix to modify the package name for a test build type.
buildTypes {
debug {
runProguard false
proguardFile 'proguard-rules.txt'
applicationIdSuffix '.dev'
versionNameSuffix '-dev'
}
}
Is it possible to use this information in a xml file. My plan is to modify the account type:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType=<<PACKAGE NAME HERE ??>>
android:icon="#drawable/icon"
android:label="#string/app_name"/>
Thanks!
Here's another temporary workaround until the Android Gradle plugin gets support for placeholders in resource files.
You can dynamically create a String resource via Gradle in the defaultConfig and/or buildTypes and/or productFlavors closure:
android {
defaultConfig {
applicationId 'com.foo.bar'
resValue 'string', 'package_name', applicationId
}
}
You can then reference it in your authenticator.xml file just like you do for the label:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="#string/package_name"
android:icon="#drawable/icon"
android:label="#string/app_name"/>
While uou can use ${packageName} to fill in the generated package name in the Manifest:
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="${packageName}"
android:icon="#drawable/icon"
android:label="#string/app_name"/>
This currently (Android Gradle 0.11) doesn't work with resource files. :-(
Instead, you must create a separate version of the resource file for each build type / variant you want with a different account type:
src
debug/res/xml/authenticator.xml (with debug package name)
main/res/xml/authenticator.xml (with default package name)
On top of jenzz's answer, i had to do this, since my case is just like as question, i add applicationIdSuffix for debug version of app.
android {
...
defaultConfig {
applicationId "..."
...
}
....
buildTypes {
release {
...
resValue 'string', 'application_id', android.defaultConfig.applicationId
}
debug {
...
applicationIdSuffix '.debug'
resValue 'string', 'application_id', android.defaultConfig.applicationId + applicationIdSuffix
} 
}
Then in any xml resource, i can get application Id as like this: #string/application_id
I'm using ${applicationId} like follow for example:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abnerescocio.embaixadordorei.presentation">
...
<application
...
>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
...
</application>
</manifest>
I've just created a gradle plugin for this: com.inutilfutil.android-resource-placeholder
Just include it and placeholders will be replaced on all XML resources

Categories

Resources