打包系列教程目录:
纯ant命令行打包android apk之图文从原理角度完全详解android打包过程(打包系列教程之一)
用ant的build.xml构建自动化打包android apk 完全详解(打包系列教程之二)
Android 多渠道打包之混淆文件ProGuard技术详解-特别篇(打包系列教程之三)
android studio gradle 多渠道打包之完全详解(打包系列教程之四)
android studio gradle 多版本多apk打包(打包系列教程之五)
详解高速神器python脚步打包android apk,超级快!!(打包系列教程之六)
好久没更新了,最近自己有点私事,所以一直没时间写博客,今天就来更新一下打包系列教程,通过前面3篇内容的学习,相信大家对android打包的流程和混淆操作已相当了解了。本篇我们就来分析多渠道自动化打包android的apk。(平台:mac;工具:android studio)
这里我们先了解一下为什么要多渠道打包?现在国内android应用市场特别多,我们每次发布app时都会根据公司的要求,把我们生成的签名包发布到相应的应用市场上,这时我们就需要把不同应用市场上的包标记上不同的渠道,比如说发布在360应用市场,这时这个包的渠道就是必须标记为360相关的标志,如果发布在腾讯的应用宝就必须标记为应用宝相关标志,那这个渠道标志又有啥用呢?这里举个例子,我公司用的是友盟多渠道打包,当渠道包都发布到相应的渠道应用市场后,我们可以通过友盟后台的渠道数据来判断我们的应用在那个市场上下载活跃量比较高,从而采取相应的策略,对app进行特定渠道的推广或者优化。当然我们在这里只是举例其中的一个功能而已,其实友盟还有很多其他的功能,这里不过多阐述。
这里为了演示更加有说服力,我们可以先集成一下友盟的统计分析功能,至于如何集成,大家直接看官网,官网的教程说得很明白(友盟官网地址:http://dev.umeng.com)。集成完成后,我们就可以开始写我们的打包程序了,这是我主要说明的是使用android studio配合gradle进行多渠道打包,现在就开始吧;
首先我们看一下集成后的AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zejian.application"> <!--友盟渠道的权限--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <!--友盟渠道app_key--> <meta-data android:value="56cfb5a3e0f55abed60023fd " android:name="UMENG_APPKEY"></meta-data> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--友盟渠道渠道号--> <meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" /> </application> </manifest>其他不用看,我们可以先看:
<!--友盟渠道渠道号--> <meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" />
${UMENG_CHANNEL_VALUE}这个就是我们要用于多渠道打包的,需要要被替换成渠道名称的占位符字段,现在先知道这点就行,后面我们会说明。
要配置多渠道打包,我们首先需要一个打包key,这个大家自己提前准备好就行,我这是使用的是我用来测试的key-->debug4zj.jks。然后配置在gradle文件中,如下:
然后在构建类型(buildTypes)中配置我们的要打包的信息:
这些都搞定后,我们就需要来配置渠道了,gradle多渠道打包是通过productFlavors来配置的,如下:
在这里需要说明一下就是productFlavors中配置的每一个flavors都代表着一个渠道的apk信息,如haiwei渠道号就代表着华为渠道的apk。那么这个渠道号又是如何替换的呢?我们可以看到manifestPlaceholders这个字段,其实可以把它理解为一个HashMap的键值对容器,通过这个键值对容器,我们就可以替换AndroidManifest.xml里面的友盟渠道配置信息即前面所说过的${UMENG_CHANNEL_VALUE}占位符字段的值,要注意名称配置一定要跟gadle中的名称一致。这样就完成了多渠道的替换循环工作,当然多渠道打包的工作也就完成了。上面的多渠道打包配置是不是很明朗也很清晰,但却略带麻烦,其实还有下面一种多渠道配置写法,显得相当简洁,不过就是不太明朗罢了,各自选择吧:
到此gradle多渠道打包的配置已经完成,我们打开as的命令行,直接执行./gradlew assembleDebug4zj,然后回车,打包就开始执行了。打包完成log如下:
接下来我们就用友盟渠道来测试一下,看看渠道号是否集成成功,这里我们使用友盟的集成测试功能,因为这个功能是实时的,方便我们观察,至于友盟集成测试功能如何使用,请大家自行参考官方文档哈。集成后我们就来进行测试吧,我使用的测试机以及未测试的数据如下:
我们以360,豌豆荚,百度的apk安装到我们的测试机器上,然后再观察友盟后台的数据,如下:
可以看到数据都实时显示出来了,说明我的多渠道打包apk没问题。到这里本该结束,但我们最后再来唠叨一下一个概念Buid Variants ,这个又是什么呢?我们先来认识一下assemble这个命令,还记得刚才我们打包所用的命令嘛?./gradlew assembleDebug4zj,对于assemble这个命令,它可以结合构建类型(buildTypes)去创建task,如下根据我们的gradle文件的buildTypes类型,我们可以创建两种Task:
assembleDebug4zj这个就是我们刚才打包执行的任务。如果我们执行assembleRelease这个任务的话,as就会根据gradle配置的构建类型去执行相应的操作。除了这个外assemble还可以结合Buid Variants来创建新的Task,而对于Buid Variants则是projectFlavors+buildTypes的结合,举个例子,比如我们想打百度渠道debug4zj版本的包,则可以在命令行输入如下命令:./ gradlew assembleBaiduDebug4zj 这样就会单独打出这个版本的包,其他包都不会有:
至为什么每次都会打出一个未zipaligned的包,我也还没搞清楚原因(知道原因的给我留一下言哈,谢了)。但签名好的包只有百度版本的渠道包,这点肯定是没错的。当然我们也可只打百度版本的而不区分构建类型也就是debug4zj和release版本都打,我们可以这样输入命令: ./gradlew assembleBaidu ,这样就会出现debug4zj和release版本的百度渠道包了。
最后献上完整的grdlew文件:
apply plugin: 'com.android.application' def releaseTime() { return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) } android { signingConfigs { debug4zj { keyAlias 'debug4zj' keyPassword 'debug4zj' storeFile file('/Users/zejian/Documents/android-studio-workplace/debug4zj.jks') storePassword 'debug4zj' } } compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.zejian.application" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" // dex突破65535的限制 multiDexEnabled true } buildTypes { debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug4zj { // 不显示Log buildConfigField "boolean", "LOG_DEBUG", "false" //是否混淆 minifyEnabled true //是否进行zipalign优化 zipAlignEnabled true // 移除无用的resource文件 shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.debug4zj applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith('.apk')) { // 输出apk名称为zejian_v1.0_2015-01-15_wandoujia.apk def fileName = "zejian_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk" output.outputFile = new File(outputFile.parent, fileName) } } } } } //配置多渠道 productFlavors { zejian { manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } huawei { manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } _360 { manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } baidu { manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } wandoujia { manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } } // // productFlavors { // zejian {} // huawei {} // _360 {} // baidu {} // wandoujia {} // } // // productFlavors.all { // flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] // } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:design:23.1.1' compile files('libs/umeng-analytics-v5.6.4.jar') }