前言
多渠道打包一般应用于向不同应用市场提交app后用来统计不同渠道下载安装量等一些信息。渠道包就是要在安装包中添加渠道信息,也就是channel,对应不同的渠道,例如:小米市场、360市场、应用宝市场等,一般来讲,这个渠道的标识会放在AndroidManifest.xml的Application的一个Metadata中。然后就可以在java中通过API获取对应的数据了。
友盟的多渠道打包方案
实现步骤
1,在AndroidManifest.xml中加入友盟的集成代码以及权限:
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
这段配置,value那里就是wandoujia,360之类的渠道名称,但是我们在这里不会去写渠道名,写的是一个占位符,后面gradle编译的时候会动态的替换掉它。
2、在module(一般也就是app)的build.gradle的android{}中添加如下内容:
productFlavors{
wandoujia{
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
xiaomi{
manifestPlaceholders=[UMENG_CHANNEL_VALUE: "xiaomi"]
}
}
productFlavors是android节点的一个子节点。你需要打什么渠道的包,就在这里按umeng的要求用渠道名给UMENG_CHANNEL_VALUE赋值。
优化1:上面只是两个渠道,如果有几十个渠道,都这样写,重复的东西太多,观察到每个渠道就是flavor的名称,所以修改如下:
productFlavors{
wandoujia{ }
xiaomi{ }
}
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
优化2:上面经过签名打包后生成的apk的名称是有默认命名规则的,如:xxx-xiaomi-release.apk 但是我们想包含版本信息如:xxx-xiaomi-release-1.0.apk,所以最终打包脚本如下:
productFlavors{
wandoujia{
}
xiaomi{
}
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
然后执行Build – Generate Signed APK,弹出如下面板:
选择需要打包的渠道即可,然后在app/build/outputs/apk中就能看到自动打好的渠道包了。
另外如果项目有要求需要我们在注册或者登录的时候将渠道信息提交给服务器端,那么如何获取到当前apk所包含的渠道信息呢,很简单,调用如下方法即可:
/**
* 获取app当前的渠道号或application中指定的meta-data * *
* @return 如果没有获取成功(没有对应值,或者异常),则返回值为空
*/
public static String getAppMetaData(Context context, String key) {
if (context == null || TextUtils.isEmpty(key)) {
return null;
}
String channelNumber = null;
try {
PackageManager packageManager = context.getPackageManager();
if (packageManager != null) {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo != null) {
if (applicationInfo.metaData != null) {
channelNumber = applicationInfo.metaData.getString(key);
}
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return channelNumber;
}
然后在需要获取渠道的地方直接调用该方法即可:
getAppMetaData(getBaseContext(), "UMENG_CHANNEL")
缺点:如果渠道过多这种打包方式很费时间20个渠道包差不多要40分钟的时间。
美团walle(瓦力)打包
在这介绍美团最新的walle打包,之前美团还有一个打包方式是通过python脚本修改apk(apk也是一个压缩包)中的一个配置文件的名称,配置文件名称也就是渠道名称从而打不不同的包,这种速度很快,但是从android7.0以后android加入了APK Signature Scheme v2打包方式,因为这种打包方式改变的包里面的内容所以apk在7.0以后的系统中安装会提示安装失败。
在此推荐美团walle打包,此种方式是不通过外部修改配置文件的方式打包。
集成方式
1,首先build.gradle中:
apply plugin: 'walle'
walle {
// 指定渠道包的输出路径
// apkOutputFolder = new File("${project.buildDir}/outputs/channels");
apkOutputFolder = new File("D:/Android/outputs/user/channels");
// 定制渠道包的APK的文件名称
// apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk';
apkFileNameFormat = 'app-${channel}-v${versionName}.apk';
// 渠道配置文件
channelFile = new File("${project.getProjectDir()}/channel")
}
dependencies {
compile 'com.meituan.android.walle:library:1.1.6'//美团多渠道打包
}
这里的 channelFile是一个channel(渠道的一个配置文件)放在该工程的对应的目录下
apkOutputFolder 是apk包生成的位置,可更改
该文件用文件编辑器打开格式如下:
2,然后在 工程的 build.gradle中加入:
dependencies {
classpath 'com.meituan.android.walle:plugin:1.1.6'
}
这种打包方式不是更改AndroidManifest的方式,所以先把AndroidManifest中的配置友盟渠道的代码注释掉:
<!--<meta-data-->
<!--android:name="UMENG_APPKEY"-->
<!--android:value="your key" />-->
<!--<!– <meta-data android:value="faqiao" android:name="UMENG_CHANNEL"/> –>-->
<!--<meta-data-->
<!--android:name="UMENG_CHANNEL"-->
<!--android:value="channel" />-->
通过调用walle的方法获取到的channel的名称,所以需要在app初始化的 BaseApplication中初始化友盟的channel配置信息。
private void initUmeng(){
String appkey = "your appkey";
String channelId = WalleChannelReader.getChannel(this.getApplicationContext());
//初始化友盟配置信息 通过代码方式配置友盟的渠道信息
MobclickAgent.UMAnalyticsConfig config =
new MobclickAgent.UMAnalyticsConfig(this, appkey, channelId);
}
配置好了那么就开始打包了,在as自带的命令输入框输入打包命令,等两分钟左右所有的渠道包就打完了!
出现BUILD SUCCESSFUL 就说明打包成功了
常用的walle打包命令
//生成所有渠道包
gradlew clean assembleReleaseChannels
// 生成单个渠道包:
gradlew clean assembleReleaseChannels -PchannelList=meituan
//生成多个渠道包:
gradlew clean assembleReleaseChannels -PchannelList=meituan,dianping
总结
如果没有渠道的限制一般用as自带的gradle打包就可以,如果渠道过多推荐使用walle打包。文中介绍的美团的python打包方式现在还有一些开发者在用,因为那种方法在构建基础apk包的时候 不选用v2打包方式是没有问题的,但是我认为v2的签名打包方式更符合现在的趋势吧,所以推荐是用美团的walle打包方式。