我们的APP很有可能要发布到各个不同应用市场,为了统计APP来源渠道,因此我们需要对APP增加渠道标识。最近,我的项目也遇到了该需求。一顿操作猛如虎(度娘),在学习和总结别人的做法和经验之后,我也记录一下自己的方式。
1、在AndroidManifest.xml中设置渠道name和value变量
<meta-data
android:name="APP_CHANNEL"
android:value="${APP_CHANNEL_VALUE}" />
2、配置渠道名称,在app module的build.gradle设置productFlavors
(1) 如果渠道不是很多,比如只有3个(百度、应用宝和豌豆荚),我们简单做如下配置即可:
productFlavors {
baidu {}
yingyongbao {}
wandoujia {}
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [APP_CHANNEL_VALUE: name]
}
(2) 如果渠道很多,比如有30多个,那上面的写法就有点繁琐了,我们可以在app module的根目录下创建channel.txt文件,然后把渠道名称保存在该文件中:
channel.txt的内容如右图
在设置了channel.txt之后,我们需要做的就是在编译时把里面的渠道值读取出来,具体方式如下:
productFlavors {
def path="./channel.txt"
file(path).eachLine { line->
"$line" {
manifestPlaceholders = [APP_CHANNEL_VALUE:line]
}
}
}
3、多渠道打包还需要指定统一的维度,即指定flavorDimensions属性
我的Android Studio的版本是3.5.2,因此在app module的build.gradle增加如下配置:
flavorDimensions APP_VERSION // APP_VERSION是定义的版本号,当然也是可以自定义,例如"default"
4、读取渠道名称
接下来我们需要做的就是把渠道名称读取出来,方式如下:
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
return appInfo.metaData.getString("APP_CHANNEL");
} catch (Exception e) {
}
5、打包版本
OK,到目前为止,配置基本完成,我们就可以进行打包了,打包就比较简单了,点几下鼠标即可,我依然在Android Studio 3.5.2为例,首先在AS的右上角找到Gradle:
然后点开它,再按照下图展开:
是不是和我的一样,有很多assemble项,当然里面还有assembleDebug和assembleRelease,想打包哪个就双击哪个就好了。打包出来的.apk文件名称是否符合你的要求呢,如果想自动加上渠道名称是否有办法呢?当然了,这个可以有:
applicationVariants.all { variant ->
variant.outputs.all { output ->
if (variant.buildType.name.equals('debug')) {
outputFileName = APP_NAME + "_${variant.versionName}_${variant.productFlavors[0].name}_debug.apk"
} else if (variant.buildType.name.equals('release')) {
outputFileName = APP_NAME + "_${variant.versionName}_${variant.productFlavors[0].name}_release.apk"
}
}
}
上面的variant.productFlavors[0].name就是渠道的名字。
经过上面的一顿操作后,基本上满足了我们的需求。不过,我踩了一个坑需要告知一下大家,在channel.txt文件中的渠道名称不可以是纯数字,因为我的获取渠道名称的方法为appInfo.metaData.getString("APP_CHANNEL"),返回的是String类型。如果把渠道名称qh360更改为360,那么就会出现类型转换错误异常:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
到此,本文记录完毕。