我们可以利用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这样,名字和产品名字是对应的。在编译的时候,默认会将这些代码集加入编译,这样就实现了不同产品,不同代码。
比如branchA 需要不同的启动和登录界面,我们就可以在branchA中加入res目录,并放入不同的布局文件
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"
}
}
}
打包的结果:
注意:
获取的productFlavors.versionName
是一个数组,如果直接使用productFlavors.versionName
的话打包出来的文件名会带“[]”,所以在使用的时候我们需要加上[0]
--> productFlavors.versionName[0]