多渠道打包
国内Android应用下载有360、小米、豌豆荚、百度等等非常多的渠道, 如果我们想统计每个渠道的下载量和活跃度,就需要使用统计平台.
我们以友盟统计为例,介绍如何配置渠道信息并执行自动化打包.
1.在AndroidMainfest.xml配置可动态替换的渠道参数
友盟集成文档中有说明,使用友盟统计需要在AndroidMainfest.xml配置相应的渠道号:
<meta-data
android:name="UMENG_CHANNEL"
android:value="xiaomi" /><!--渠道号为:小米-->
如果想动态的替换渠道号怎么办呢?
<meta-data
android:name="UMENG_CHANNEL"
android:value="${CHANNEL_ID}" /><!--动态替换渠道号-->
2.在build.gradle中配置渠道信息和自动替换脚本
// 多渠道打包
productFlavors {
xiaomi {} //渠道名name为xiaomi
baidu {}
wandoujia {}
// 自动替换AndroidManifest.xml中的渠道号
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [CHANNEL_ID: name]
}
}
配置好以后在Build Variants窗口中可以选择不同渠道的变种版本:
Gradle工具栏也会生成相应的任务:
3.默认配置
// 默认配置
defaultConfig {
applicationId "com.wirelessqa.basebuildsample" //apk包名
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0" //版本号
//android单元测试test runner
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
所有渠道默认使用这一配置,如果渠道有特殊需求,可以在productFlavors对应的渠道号中单独配置.
4.打包后自动修改apk的名字
// 打包后自动修改apk的名字
// release包的命名格式为:产品名_版本号_渠道号.apk
// debug包的命名格式为:产品名_版本号_渠道号_Debug_打包时间.apk
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (null != outputFile && outputFile.name.endsWith('.apk')) {
File outputDir = new File(outputFile.parent);
def baseName = PRODUCT_NAME + "${defaultConfig.versionName}" + "_" + variant.productFlavors[0].name
def newApkName
if (variant.buildType.name.equals('release')) {
newApkName = baseName + '.apk'
} else if (variant.buildType.name.equals('debug')) {
newApkName = baseName + "_Debug_${packageTime()}.apk"
}
output.outputFile = new File(outputDir, newApkName)
}
}
}
5.自动化打包
如何一次打出所有渠道的Release的包呢?
方法一: 命令行:
$ ./gradlew assembleRelease
方法二: Gradle工具窗口:
方法三: 菜单栏 —> Build —> Generate Signed APK —> 一步步下去 —> Flavors中全选—> Finish.
这样所有渠道的Release包都被打出来了.
6.查看渠道号是否被正确替换.
单击apk之后,Android Studio会自动解析apk,这样我们就可以在Android Studio中直接查看apk的信息了.
1.单击baidu这个渠道 —>2.点击AndroidManifest.xml —>3.查看渠道号为baidu
由此证明我们的打包脚本是OK的.
如果要打Debug包,执行assembleDebug任务就可以了.
如果只想打某一个渠道的包,执行对应的打包任务就可以了.
本例中全部的build.gradle脚本如下:
//插件:
//这个module是一个android程序,使用com.android.application
//如果是android库,应该使用com.android.library
apply plugin: 'com.android.application'
//产品名
def PRODUCT_NAME = "wirelessqa"
//打包时间
def packageTime() {
return new Date().format("MMddhhmmss", TimeZone.getTimeZone("GMT+8"))
}
android {
// 签名配置
signingConfigs {
MySigning {
keyAlias 'myandroid'
keyPassword '123456'
storeFile file('/Users/bixiaopeng/myandroid.jks')
storePassword '123456'
}
}
// 编译sdk版本
compileSdkVersion 23
// 构建工具版本
buildToolsVersion "23.0.2"
// 默认配置
defaultConfig {
applicationId "com.wirelessqa.basebuildsample" //apk包名
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName "1.0" //版本号
//android单元测试test runner
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
versionNameSuffix 'test'
}
// 产品特性
productFlavors {
xiaomi {} //渠道名name为xiaomi
baidu {
}
wandoujia {}
// 自动替换AndroidManifest.xml中的渠道号
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [CHANNEL_ID: name]
}
}
// 构建类型,此处配置debug和release版本的一些参数,像混淆、签名配置.
buildTypes {
// release包的配置
release {
//开启混淆
minifyEnabled true
// 指定混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// 指定签名配置
signingConfig signingConfigs.MySigning
zipAlignEnabled true
//移除无用的资源文件
shrinkResources true
}
}
// 打包后自动修改apk的名字
// release包的命名格式为:产品名_版本号_渠道号.apk
// debug包的命名格式为:产品名_版本号_渠道号_Debug_打包时间.apk
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (null != outputFile && outputFile.name.endsWith('.apk')) {
File outputDir = new File(outputFile.parent);
def baseName = PRODUCT_NAME + "${defaultConfig.versionName}" + "_" + variant.productFlavors[0].name
def newApkName
if (variant.buildType.name.equals('release')) {
newApkName = baseName + '.apk'
} else if (variant.buildType.name.equals('debug')) {
newApkName = baseName + "_Debug_${packageTime()}.apk"
}
output.outputFile = new File(outputDir, newApkName)
}
}
}
}
// 依赖的第三方库
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha1'
compile 'com.android.support:design:23.4.0'
testCompile 'junit:junit:4.12'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support:support-annotations:23.4.0'
}