一、使用Androis Studio自带的productFlavors
productFlavors的功能非常强大,但用起来真的太慢,即使不是很大的项目,你也受不了那个速度。之所以慢,也是因为他的强大。比较适合Google play发布吧,毕竟人家支持根据机型下载不同的安装包(比如按平台打包so文件)。国内的情况,一般都不支持,渠道也只不过是用一个字符串区分,其他都一样。确实没必要用productFlavors。这里还是记录下用法:
1、在app module 的builde.gradle 的android{}闭包下配置
//多渠道打包,下面是需要配置的渠道,名称自定义,自己能区分就行
productFlavors {
alphaTest {}
alibaba {}
xiaomi {}
googlePlay {}
official {}
yingyongbao{}
huawei{}
qh360 {}
baidu {}
kuan {}
}
productFlavors.all {//会替换AndroidManifest下配置的变量,达到区分不同渠道的目的
flavor -> flavor.manifestPlaceholders = [STORE_CHANNEL_VALUE: name]
}
2、AndroidManifest下application标签下添加
3、获取渠道信息的方法
//可能返回空,需要自己判断
public static String getAppChannel(Context context) {
ApplicationInfo appInfo;
try {
appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
return appInfo.metaData.getString("STORE_CHANNEL");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
}
二、使用一些开源的工具,这里推荐腾讯的VasDolly
1、先说些相关的
这里推荐一片文章,关于V1,V2签名,以及多渠道打包工具的原理:
借腾讯开源 VasDolly,谈谈 Android 签名和多渠道打包的原理
VasDolly Github网址:
https://github.com/Tencent/VasDolly
详细的使用方法,上面的网址里的文档已经写的很清楚了。有一个注意点就是目前按照github文档(2018/3/9)根据基础包生成多渠道包的rebuildChannel不能配置文件名,实际上也是可以的,但不是那么直接(这里和维护的工程师交流过了,说会加上说明)。
rebuildChannel {
//指定渠道文件
//channelFile = file("/Users/leon/Downloads/testReChannel.txt")
//注意这个文件名base.apk
baseReleaseApk = new File("C:/Android/Project-3.0/ProjectName/", "apk-base/base.apk"
releaseOutputDir = new File(project.buildDir, "rebuildChannel/release")
//快速模式:生成渠道包时不进行校验(速度可以提升10倍以上)
isFastMode = false
}
文档里没有说明的一个规则:渠道名会替换基础包名称里的base字符串。
以上面的配置为例,假设你有渠道名是kuan,那么执行rebuildChannel后的输出的文件名就是kuan.apk(base--->kuan)。
如果上面的baseReleaseApk名称做下修改:
baseReleaseApk = new File("C:/Android/Project-3.0/ProjectName/",
"apk-base/app_base_V1.0_release.apk"
那么最后输出的文件名就是app_kuan_V1.0_release.apk
2、结合AndResGuard使用VasDolly
2.1、添加依赖
Project的build.gradle
buildscript {
repositories {
jcenter()
google()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.11'
classpath 'com.leon.channel:plugin:1.1.7'
}
}
主module app的build.gradle添加插件
apply plugin: 'AndResGuard'
apply plugin: 'channel'
主module app的build.gradle添加依赖(只有这一个,用于获取渠道信息,其他方面这两个工具都不涉及编译过程)
dependencies {
api 'com.leon.channel:helper:1.1.7'
}
主module app的build.gradle 配置
rebuildChannel {//从此,打包效率提高十倍以上,即使不开FastMode
//这里的目录都是自己定义的,我这里是动态的设置包的名称的,由于versionName比较长,就截取了一段
baseDebugApk = new File("C:/Android/Project-3.0/ProjectName/", "apk-base/denglu1-" +
"${android.defaultConfig.versionName.substring(0, 6)}-base-debug.apk")
debugOutputDir = new File("C:/Users/Bright/Desktop/", "rebuildChannel/debug")
baseReleaseApk = new File("C:/Android/Project-3.0/ProjectName/", "apk-base/denglu1-" +
"${android.defaultConfig.versionName.substring(0, 6)}-base-release.apk")
releaseOutputDir = new File("C:/Users/Bright/Desktop/", "rebuildChannel/release")
//快速模式:生成渠道包时不进行校验(速度可以提升10倍以上)
isFastMode = false
}
andResGuard {
// mappingFile = file("./resource_mapping.txt")
mappingFile = null
// 使用v2签名和7zip压缩是冲突的(但他是不会报错的)。
// 如果用了V2,这里就必须false,不然生成的包无法安装。
use7zip = false
useSign = true
// 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字
keepRoot = false
whiteList = [
"R.mipmap.ic_launcher",
"R.mipmap.ic_launcher_round",
"R.drawable.push_small"
]
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
"resources.arsc"
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.11'
//path = "/usr/local/bin/7za"
}
//这里配置的是输出的目录,名称是动态的,可以参考下这种写法buildTypes就是release/debug/...看你配置了几种了
finalApkBackupPath = "C:/Android/Project-3.0/ProjectName/apk-base/denglu1-" +
"${android.defaultConfig.versionName.substring(0, 6)}" +
"-base-" +
"release.apk"
}
主module app的build.gradle android{}闭包里配置签名信息,这里同时使用了V1、V2签名:
signingConfigs {
//在这里配置相关的签名信息
keyStore {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def keystoreFilePath = properties.getProperty("KEY_STORE_FILE_PATH")
def storePsw = properties.getProperty("KEY_STORE_PASSWORD")
def alias = properties.getProperty("KEY_ALIAS")
def keyPsw = properties.getProperty("KEY_PASSWORD")
storeFile file(keystoreFilePath)
storePassword storePsw
keyAlias alias
keyPassword keyPsw
v1SigningEnabled true
v2SigningEnabled true
}
}
channel.txt:
alibaba
xiaomi
googlePlay
official
yingyongbao
huawei
qh360
baidu
channel.txt我是放在Project根目录下,然后在gradle.properties里配置的:
channel_file=channel.txt
你也可以在rebuildChannel{}闭包里配置,具体参照VasDolly的Github文档
获取渠道信息的方法:
public static String getAppChannel(Context context) {
String channel = ChannelReaderUtil.getChannel(context.getApplicationContext());
if (channel == null) {//防止debug直接安装时,获取为空,事实上,也只有release时才需要多渠道
return "alphaTest";
} else {
return channel;
}
}
最后,先resguardRelease
生成基础包,然后rebuildChannel生成多渠道包,收工。
也可以编辑gradle task,做成一个task搞定(其实没多大差别了)。