How to use sourceSets to replace/override app icon in gradle - android

I'd like to use different icon in different flavor.
There's a default icon in my main sourceSets (in dir src/main/res/mipmap-*dpi), and I try to replace/override icon in build.gradle with sourceSets.
buildTypes {
release {
...
}
debug {
...
}
}
flavorDimensions "d1", "d2"
dimension11 {
dimension "d1"
}
dimension21 {
dimension "d2"
sourceSets.debug {
resources {
srcDir 'config/icon/free' // my icon is in free/res/mipmap-*dpi
exclude 'src/main/res/mipmap-*dpi' //not working, mipmap-*dpi and mipmap-*dpi-v4 are all in the final apk file.
}
}
}
dimension22 {
dimension "d2"
}
dimension23 {
dimension "d2"
}
It's not working, mipmap-*dpi and mipmap-*dpi-v4 are all in the final apk file. mipmap-*dpi-v4 are generated by agp.
If I rename mipmap-*dpi which in dir config/icon/free to mipmap-*dpi-v4, then:
Entry name 'res/mipmap-hdpi-v4/ic_launcher.png' collided
If I remove files which are in src/main/res/mipmap-*dpi,
AAPT: error: resource mipmap/ic_launcher (aka mypackage:mipmap/ic_launcher) not found.
So how can I replace or override app icon? Can I achieve that with custom sourceSets?
TASK: installDimension11Dimension21Debug
GRADLE: 6.8.3
AGP: 4.1.3

To use different app icons for different flavors, you need to create directory under src dir on the name of flavor. Add mimap folders under that dir with app icons.

Related

Product flavors in android not working

I have been stuck on this for a day now. I created 2 flavors for my project and added them under the buildtype in android in build.gradle. I then created a res folder for both and changed the icons for each. When I run the project for any of the variants, it is showing the icon from the project.
My project structure in as follows
[project]
[app]
src
main
res
mipmap
flavor1
flavor2
res
mipmap
and my build.gradle is
productFlavors {
flavor1 {
applicationId "abc"
}
flavor2 {
applicationId "abc"
}
}
sourceSets {
flavo1 {
res.srcDirs = ['src/flavor1/res']
}
flavor2 {
res.srcDirs = ['src/flavor2/res']
}
}
PS: nvm the naming
You should remove the icon from main and leave it only in flavor1 and flavor2 directories.
Also check the names of the flavors in the build.gradle, I think it should be flavor1 instead of flavo1 and flavor2 instead of staging.
Another note, sourceSets definition is not required, standard res directories inside flavors' directories will be used automatically.

Android Gradle identify current falvor at compile time

How is it possible to identify the current flavor being compiled. I'm trying to add a file to compile only if I'm compiling a certain product flavor.
buildTypes {
android.applicationVariants.all { variant ->
variant.productFlavors.each() { flavor ->
if (flavor.name.equals(currentFlavorName)) {
The problem is that I can't seem to find where the currentFlavourName of the flavor which I am currently building is located.
just put the strings you want for flavor1 into:
src/flavor1/res/values/strings.xml
and the strings for flavor2 into:
src/flavor2/res/values/strings.xml
no need to put logic into your gradle file
Android uses a unique build process regarding your resources for different flavors and it is very easy to control.
if you set up your main source:
project-name
------------/app
---------------/src
-------------------/main
------------------------/res
----------------------------/values
------------------------/java
-------------------/development
-------------------------------/res
-----------------------------------/values
-------------------------------/java
-------------------/production
------------------------------/res
----------------------------------/values
------------------------------/java
This would be a bottom up approach from product flavor into main. Meaning if you have a strings.xml with items having the same name existing in development/res/values and have values that also exist in main/res/values/strings.xml these will be over written (and same would go for the production flavor) based on the build variant defined in your gradle file.
android {
productFlavors {
production {
applicationId "com.test.prod"
versionName "1.0.0"
}
development {
applicationId "com.test.dev"
versionName "1.0.0"
}
}
I don't know if exits a method to get the currentFlavor. I haven't found it yet.
A ugly solution can be
variant.productFlavors.each() { flavor ->
if (flavor.name.equals("flavor1")) {
//..........
}
}
However, if you want to be able to control which strings.xml you are using, you can achieve it in different ways.
First of all you can just define a xml file in your flavor folder.
app/src/main/res/values/ -> for common resources
app/src/flavor1/res/values -> resources for flavor1
app/src/flavor2/res/values -> resources for flavor2
This doesn't require any config in your build.gradle script.
A second option is to define a resource value using build.gradle.
Something like:
productFlavors {
flavor1 {
resValue "string", "app_name", "IRCEnterprise"
}
//....
}
Another option is to create some field in your BuildConfig class using this kind of script.
productFlavors {
flavor1 {
buildConfigField "String", "name", "\"MY FLAVOR NAME\""
}
}

Export environment variables in build.gradle

Gradle supports multiple flavor builds for Android Applications. How can I export an environment variable which has different flavor values? For example, export FLAVOR with value "flavor1" when flavor1 is built and "flavor2" for flavor2 build.
android {
...
productFlavors {
flavor1 {
...
}
flavor2 {
...
}
}
}
This link http://inaka.net/blog/2014/12/22/create-separate-production-and-staging-builds-in-android/ may help you out.
If you have two productFlavors (Production and Staging, for instance)
You should create two different resource folders:
project/app/src/production/res/values/strings.xml
<resources>
<string name="root_url">http://production.service.com/api</string>
</resources>
project/app/src/staging/res/values/strings.xml
<resources>
<string name="root_url">http://staging.service.com/api</string>
</resources>
You should add this following code inside the android {}:
productFlavors {
production {
applicationId "com.inaka.app.production"
}
staging {
applicationId "com.inaka.app.staging"
}
}
It's a good idea to have different icons for different productFlavors, just add the icon inside each different resource folder.

Combine BuildType and Flavor resources

I have 2 versions of app: paid-app and free-app. I use gradle and Android Studio.
I have next folder structure:
src folder, and inside it 3 folders: main, paidapp, freeapp - where paidapp and freeapp are flavors.
My configs:
defaultConfig {
applicationId "com.company"
}
buildTypes {
debug {
applicationIdSuffix '.dev'
}
}
productFlavors {
freeapp {
}
paidapp {
applicationId 'com.company.paidapp'
}
}
What I want: have on my phone 4 apps:
package com.company.dev, name "dev freeapp"
package com.company.paidapp.dev, name "dev paidapp"
package com.company, name "freeapp"
package com.company.paidapp, name "paidapp"
package is ok, gradle manage it automatically, but how to create different names for app?
App name located in strings.xml
in src/paidapp/res/values/strings.xml:
<string name="appName">dev paidapp</string>
in src/freeapp/res/values/strings.xml:
<string name="appName">dev freeapp</string>
I looked there - http://tools.android.com/tech-docs/new-build-system/resource-merging
The priority order is the following:
BuildType -> Flavor -> main -> Dependencies.
So I can chose or string from BuildType or from Flavor, but how to combine BuildType and Flavor?
Just create a folder src/freeappRelease/res/values/ and add your very specific strings in this folder.

How to provide different Android app icons for different gradle buildTypes?

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.

Categories

Resources