119

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'])
}
InsanityOnABun
  • 5,193
  • 5
  • 18
  • 25
  • check this http://stackoverflow.com/questions/18460095/how-to-provide-different-launcher-icon-per-product-flavour – Libin Apr 05 '14 at 02:56
  • 3
    Possible duplicate of [Android - app icon for debug and release mode](http://stackoverflow.com/questions/19528063/android-app-icon-for-debug-and-release-mode) – Jose Gómez Feb 04 '17 at 20:15

5 Answers5

176

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.

InsanityOnABun
  • 5,193
  • 5
  • 18
  • 25
  • Did you not have to specify the additional debug folder with a sourceSets declaration? – ncoronges Apr 24 '14 at 11:06
  • 1
    @ncoronges I did not. It would seem since debug is a built-in build type, the source set for it is built-in as well. – InsanityOnABun Apr 25 '14 at 15:54
  • Did you leave all your other resources in the common "main" folder? Is the release icon still in the "main" folder too? You have no other settings in AndroidManifest or build.gradle? I'm not getting an icon change when I try this. – Scott Jun 20 '14 at 13:52
  • 1
    @Scott It works for me using 'debug' if I just put my icon in each drawable folder. E.g. drawable-mdpi, drawable-hdpi, etc. I don't need any of the other resources or code in the debug folder. – roarster Jul 21 '14 at 06:19
  • More details (same information) here: https://peirr.com/random-android-gradle-tip-different-icon-per-buildtype/ – Jesse Chisholm Aug 22 '18 at 17:15
  • 3
    works like charm. Just had to copy all mipmap directories in debug folder – Amit Bhandari Oct 16 '18 at 06:38
  • 1
    How to have a different app name? – DKV Dec 20 '18 at 11:52
103

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

Hardy Android
  • 791
  • 9
  • 17
qinmiao
  • 4,349
  • 4
  • 33
  • 39
  • 1
    This is a handy approach although it has an important downside... both launchers will be put into your apk. – Bartek Lipinski Sep 28 '16 at 14:14
  • -_-# It's a Problem, I update it.The better way: -->http://stackoverflow.com/a/22876224/703225 – qinmiao Oct 01 '16 at 02:57
  • 2
    why it is important downside? it doesn't look too important to me, and it is good and clean gradle solution – luky Oct 10 '16 at 09:27
  • 2
    I second @luky's question. Why is this a downside? I would think adding additional top-level directories (I have four different build variants in my project) is less clean than using manifest placeholders. Especially when those directories contain just a single icon. – GregSantulli Apr 28 '17 at 14:39
  • If you want to use this way and stop adding both icons to the production APK, you can set the `manifestPlaceholders` only in the execution phase or behind and `if` statement. I'm doing this because I have 1 non-production build type that can have two different icons (and I don't want to have an entire build type with only 1 difference with the other one) – Nahuel Barrios Aug 24 '17 at 23:17
  • This works really well for different icons for different flavors (prod, dev, qa, etc) – BlackHatSamurai Oct 20 '17 at 17:22
  • What do you mean by `both launchers`? are you talking about the icons? – casolorz Mar 10 '18 at 00:03
  • The better way: InsanityOnABun's answer -> https://stackoverflow.com/a/22876224/703225 – qinmiao Mar 10 '18 at 05:22
  • Using a proper folder structure is better for multiple reasons: it's less error-prone (all your resources are switched automatically at compile time, not only the one referenced by a different name in a manifest), and your images are not bundled in your final APK. Bundling useless resources just because you find an approach cleaner is not really a good way of doing things... especially when this approach is not cleaner, but going against the platform tooling. – Marc Plano-Lesay Nov 03 '18 at 22:16
  • Hi, your answer is good there are other ways, but wanted to at least make sure you by now are aware that you can add useProguard true shrinkResources true //remove unused resources per flavor minifyEnabled true, to your buildType and that will scrape out the unused resources for that particular build. You can update your answer if you want to include that, so people know about it. personally I prefer this to a hundred flavor folders flavorADebug, flavorAQa, flavorBDebug, flavorBStaging, etc.. gets VERY VERBOSE, I hate that personally. – Sam Oct 15 '19 at 00:20
  • I think that best solution, but you should use both solutions (this solution and first solution of this question), they so good in combination – Arsen Feb 12 '21 at 08:18
12

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

isyi
  • 1,172
  • 1
  • 10
  • 11
  • 4
    Check the question. "Is there any way to this just through the build type, **without getting into product flavors**?" – InsanityOnABun Jan 04 '15 at 03:38
  • 5
    While not as asked, did helped me a lot! ~using flavours~ – Flummox - don't be evil SE Jul 25 '16 at 13:36
  • 2
    Best way to do it, if you already have flavor specific manifest files. – Zax Apr 06 '17 at 09:35
  • This is the only solution I've seen so far where you can maintain unique names for the launcher icons .. vs. having 10+ versions of `ic_launcher.png` , having to know which one is which only by where it's located or actually opening it (not so nice). I didn't know this kind of *extending for the manifest file* was even possible, haven't seen it mentioned anywhere else on SO or otherwise before here. Elegant for sure – Gene Bo Jan 03 '18 at 20:57
7

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'
}
Jose Gómez
  • 2,891
  • 2
  • 28
  • 52
  • Not sure how this would help since the launch icon is declared in the manifest file. Can you address that issue? – David Rector Dec 17 '17 at 01:12
  • 4
    The resource name is declared in the manifest, but you can have different icons with the same file names in different flavor-specific folders as described in my post. – Jose Gómez Dec 18 '17 at 10:47
1

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.

Robert Pal
  • 556
  • 1
  • 4
  • 14