我们可以利用Gradle 实现Android的 多渠道定制化打包


ProductFlavors

同时生成多渠道多版本的操作主要是靠productFlavors 来实现的,branchA、branchB 是自定义的渠道名,这里定义的类型会在最终打包的时候出现,选择其中自己需要版本进行最终的打包即可(可多选)。

android{
    productFlavors{
        branchA{
            #这里定义渠道A包的特性
        }

        branchB{
            #这里定义渠道B包的特性
        }

        #更多 ..
    }

1、不同的applicationId 和版本号

自定义打包时间

def versionTime() {
    return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
}
...
android{
    productFlavors{       
     branchA { // 版本A
            applicationId "com.zuo.product.branchA"
            versionCode 100
			versionName "1.0." + versionTime()
        }

     branchB { // 版本B
            applicationId "com.zuo.product.branchA "
            versionCode 100
			versionName "1.0." + versionTime()
        }
	}
}

2、多渠道设置,manifestPlaceholders

比如不同的包,需要使用不同的高德地图的key(其他类似需求处理方式相同)。

1、在build.gradle 文件中设置 manifestPlaceholders ,注意key需要相同。

android{
    productFlavors{       
     branchA { // 版本A
            applicationId "com.zuo.product.branchA"
            versionCode 100
			versionName "1.0.0"
			manifestPlaceholders = [GAO_DE_KEY: "12345674646313454sdad45sw4s5awad"]
        }

     branchB { // 版本B
            applicationId "com.zuo.product.branchA "
            versionCode 100
			versionName "1.0.0"
			manifestPlaceholders = [GAO_DE_KEY: "7as4dsdads4a4d54567s53d174764assd"]
        }
	}
}

2、在manifest使用,格式是:${key}

<meta-data
            android:name="com.amap.api.v2.apikey"
            android:value="${GAO_DE_KEY}"/>

3、如果你要替换多个属性,则只需要将 manifestPlaceholders 的写法如下:

manifestPlaceholders = [VALUE_NAME1 : "value" , VALUE_NAME2 : "value"]

3、不同的版本引用不同jar包

版本名+Compile,引入不同的jar包

dependencies {
    branchACompile 'com.github.bumptech.glide:glide:2.0.6'
    branchBCompile 'com.github.bumptech.glide:glide:3.0.7'
}

4、不同版本使用不同资源文件或者代码

gradle中有一个source set的概念,对于不同的产品,可以设置不同的source set。通常,创建工程后,AndroidStudio默认帮我们创建了应用于所有产品的代码集main,它的对应的目录是src/main,我们也可以创建每个产品特有的代码集src/productA,src/productB这样,名字和产品名字是对应的。在编译的时候,默认会将这些代码集加入编译,这样就实现了不同产品,不同代码。

Android rom定制 density选择 androlua定制版_多渠道打包

比如branchA 需要不同的启动和登录界面,我们就可以在branchA中加入res目录,并放入不同的布局文件

Android rom定制 density选择 androlua定制版_android_02


Android rom定制 density选择 androlua定制版_4s_03


5、功能定制, BuildConfig

  • debug 和 release 版本的功能区别
    有很多客户需要的功能不一样,我们可以关掉一些常用的配置开关,比如推送,自动更新等等,那么可以用buildTypes来进行实现。
buildTypes {
    release {
        minifyEnabled false
        buildConfigField "boolean", "isAuto", "true"
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

    debug {
        minifyEnabled true
        buildConfigField "boolean", "isAuto", "false"
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

这样我们就给自己的app设置了一个推送标识开关,那么java代码可以这样做:

if (BuildConfig.isAuto) {
      //...         
}

Android BuildConfig 自带的一些参数

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.example.yztrtklib";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";

 }

我们也可以使用BuildConfig.BUILD_TYPE进行判断

if (BuildConfig.BUILD_TYPE) {
      //...         
}

  • 不同渠道包的功能区别

定义不同渠道版本的相同属性的不同值

android{
    productFlavors{       
     branchA {// 版本A
            applicationId "com.zuo.product.branchA"
            versionCode 100
			versionName "1.0.0"
			manifestPlaceholders = [GAO_DE_KEY: "12345674646313454sdad45sw4s5awad"]
			buildConfigField "boolean", "isMultiVersion", "true"
        }

     branchB {// 版本B
            applicationId "com.zuo.product.branchA "
            versionCode 100
			versionName "1.0.0"
			manifestPlaceholders = [GAO_DE_KEY: "7as4dsdads4a4d54567s53d174764assd"]
			buildConfigField "boolean", "isMultiVersion", "false"
        }
	}
}

3、在java代码中使用

if (BuildConfig.isMultiVersion ) {
      //TODO    
}

使用BuildConfig的FLAVOR字段
BuildConfig的FLAVOR对应的是不同的渠道名,使用如下:

if ("branchA ".equals(BuildConfig.FLAVOR)) {
	json = mContext.getString(R.string.test_branchA_json);
} else {
	json = mContext.getString(R.string.test_branchB_json);
}

6、根据定制功能的不同修改apk命名

通常我们使用不同的渠道包的时候需要在apk的命名上进行一个区分,方便发包或使用人员辨别,比如我们apk的命名规则就是:【软件名】+【大版本号】+【打包日期】+【渠道标识】

具体的使用:

def versionTime() {
    return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
}

android{

	//...

    buildTypes {
        debug {
            manifestPlaceholders = [APP_NAME: "@string/app_name_debug"]
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        release {
            manifestPlaceholders = [APP_NAME: "@string/app_name"]
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
            applicationVariants.all { variant ->
                variant.outputs.all {
                    outputFileName = "调查举证一体化软件_${productFlavors.versionName[0]}${npstr}.apk";
                }
            }
        }
    }

    flavorDimensions("channel")
    productFlavors{       
		branchA {// 版本A
            applicationId "com.zuo.product.branchA"
			signingConfig signingConfigs.release
            versionCode 1000
            versionName "3.0.${versionTime()}_单_s"
            buildConfigField "boolean", "isMultiVersion", "false"
			dimension "channel"
        }

		branchB {// 版本B
            applicationId "com.zuo.product.branchB"
			signingConfig signingConfigs.release
            versionCode 1000
            versionName "3.0.${versionTime()}_多_s"
            buildConfigField "boolean", "isMultiVersion", "true"
			dimension "channel"
        }
		branchC {// 版本C
            applicationId "com.zuo.product.branchC"
			signingConfig signingConfigs.release
            versionCode 1000
            versionName "3.0.${versionTime()}_多_浙_s"
            buildConfigField "boolean", "isMultiVersion", "true"
			dimension "channel"
        }
    }
}

打包的结果:

Android rom定制 density选择 androlua定制版_多渠道打包_04

注意:
获取的productFlavors.versionName是一个数组,如果直接使用productFlavors.versionName的话打包出来的文件名会带“[]”,所以在使用的时候我们需要加上[0] --> productFlavors.versionName[0]