SoFunction
Updated on 2025-03-01

Android Studio usage tutorial (VI): Gradle multi-channel package

Due to the many channels in the domestic Android market, in order to count the downloads and other data statistics of each channel, we need to package each channel separately. If you ask you to buy dozens of market packages, wouldn’t it be annoying? However, with Gradle, this is no longer a problem.

Youmeng multi-channel package

Without further ado, taking the Youmeng Statistics as an example, there will be a paragraph in it:

Copy the codeThe code is as follows:

<meta-data
    android:name="UMENG_CHANNEL"
    android:value="Channel_ID" />

The Channel_ID inside is the channel label. Our goal is to automatically change this value during compilation.

Step 1 Configure PlaceHolder

Copy the codeThe code is as follows:

<meta-data
    android:name="UMENG_CHANNEL"
    android:value="${UMENG_CHANNEL_VALUE}" />

Step 2 Set up productFlavors
Copy the codeThe code is as follows:

android { 
    productFlavors {
        xiaomi {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
        }
        _360 {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"]
        }
        baidu {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
        }
        wandoujia {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
        }
    } 
}

Or batch modification
Copy the codeThe code is as follows:

android { 
    productFlavors {
        xiaomi {}
        _360 {}
        baidu {}
        wandoujia {}
    } 

    {
        flavor -> = [UMENG_CHANNEL_VALUE: name]
    }
}

Very simple and clear? Execute ./gradlew assembleRelease directly, and then you can quietly drink a cup of coffee and wait for the packaging to be completed.

Assemble combined with Build Variants to create task

The previous blog introduced the assemble command, which will create your own task in combination with Build Type, such as:

Copy the codeThe code is as follows:

./gradlew assembleDebug

./gradlew assembleRelease


In addition, assemble can also be used in combination with Product Flavor to create new tasks. In fact, assemble is used in combination with Build Variants, and Build Variants = Build Type + Product Flavor. For example, you will understand:

If we want to package the release version of the Wandoujia channel, just execute the following command:

Copy the codeThe code is as follows:

./gradlew assembleWandoujiaRelease

If we only call the wandoujia channel version, then:
Copy the codeThe code is as follows:

./gradlew assembleWandoujia

This command will generate Release and Debug versions of the wandojia channel

Similarly, I want to play all Release versions:

Copy the codeThe code is as follows:

./gradlew assembleRelease

This command will print out the Release versions of all channels under Product Flavor.

In short, the assemble command creates a task as follows:

**assemble**: Allows you to directly build a Variant version, such as assemblyFlavor1Debug.

**assemble**: Allows the build of all APKs with the specified Build Type. For example, assembleDebug will build two Variant versions, Flavor1Debug and Flavor2Debug.

**assemble**: Allows the construction of all APKs for the specified flavor. For example, assembleFlavor1 will build two Variant versions, Flavor1Debug and Flavor1Release.

Complete gradle script

Finally, the benefits are given, and I will use a complete gradle file configuration I used in the project:

Copy the codeThe code is as follows:

apply plugin: ''

def releaseTime() {
    return new Date().format("yyyy-MM-dd", ("UTC"))
}

android {
    compileSdkVersion 21
    buildToolsVersion '21.1.2'

    defaultConfig {
        applicationId ".*"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
       
// dex breaks through the limit of 65535
        multiDexEnabled true
// The default channel is umeng
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "umeng"]
    }

    lintOptions {
        abortOnError false
    }

    signingConfigs {
        debug {
            // No debug config
        }

        release {
            storeFile file("../")
            storePassword "your password"
            keyAlias "your alias"
            keyPassword "your password"
        }
    }

    buildTypes {
        debug {
// Show Log
            buildConfigField "boolean", "LOG_DEBUG", "true"

            versionNameSuffix "-debug"
            minifyEnabled false
            zipAlignEnabled false
            shrinkResources false
            signingConfig
        }

        release {
// Log is not displayed
            buildConfigField "boolean", "LOG_DEBUG", "false"

            minifyEnabled true
            zipAlignEnabled true
// Remove useless resource files
            shrinkResources true
            proguardFiles getDefaultProguardFile(''), ''
            signingConfig

            { variant ->
                { output ->
                    def outputFile =
                    if (outputFile != null && ('.apk')) {
// The output apk name is boohee_v1.0_2015-01-15_wandoujia.apk
                        def fileName = "boohee_v${}_${releaseTime()}_${[0].name}.apk"
                        = new File(, fileName)
                    }
                }
            }
        }
    }

// Youmeng multi-channel package
    productFlavors {
        wandoujia {}
        _360 {}
        baidu {}
        xiaomi {}
        tencent {}
        taobao {}
        ...
    }

    { flavor ->
        = [UMENG_CHANNEL_VALUE: name]
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile ':support-v4:21.0.3'
    compile ':butterknife:6.0.0'
    ...
}

If you have any questions or questions or suggestions, please leave a message on the blog. The Android Studio tutorial is over here. I believe everyone can use it basically. There are other techniques and operations that you can explore by yourself. In the future, if you have time, you will sort out some Tips on the blog. Everyone is welcome to follow.