实际应用开发中,我们会遇到多渠道打包的情况,这是属于比较常见的,但更复杂的需求,如指定渠道使用指定包名, 甚至指定应用名、图标来打包APK, 这种情况下,通常情况下是去手动更改manifest。本文将介绍使用gradle结合shell脚本来自动化打包:
Gradle多渠道打包非常方便, 相比ANT去写循环打包脚本, gradle里只需写极少量的配置代码即可, 其余的工作均由gradle自身来完成。
下面,将给出具体的步骤。
在manifest里面, 添加一项用于记录渠道号的meta字段项, 例如:
<meta-data
android:name="channel"
android:value="${CHANNEL_VALUE}"
/>
其中的, CHANNEL_VALUE字段,将在gradle执行打包脚本时动态替换为相应渠道号。
productFlavors {
wandoujia {
manifestPlaceholders = [CHANNEL_VALUE: "123"]
}
baidu {
manifestPlaceholders = [CHANNEL_VALUE: "234"]
}
}
在build.gralde的android{ }代码块里, 添加形如以上代码, 其中wandoujia、baidu指代具体的不同的渠道, manifestPlaceholders = [CHANNEL_VALUE:XXX] 为对应的渠道号, 在打相应渠道包的时候,动态替换成相应值。
完成以上两个简单的步骤, 就可以执行 ./gradlew assembleRelease来完成多渠道打包了。 与ANT打包相比, 是不是非常简单? 当然, 我们也可以只打出以上渠道中的某一种或某几种渠道包。
只需要执行, ./gradlew assembleWandoujiaRelease 即可。 注:渠道名的首字母(wandoujia)大写。
通过以上简单的步骤, 就可以完成绝大部分的打包需求了。但是, 如果我们想针对不同的渠道指定不同应用名(manifest里的Application项对应的android:label字段值)、包名,甚至是应用图标, 我们就需要写额外的代码了, 但是,步骤也是非常简单的。下面一一介绍。
与上面一样, 这里仍然需要对build.gradle进行相应改动。示例如下:
productFlavors {
wandoujia {
applicationId = "com.package.wandoujia"
manifestPlaceholders = [CHANNEL_VALUE: "123"]
}
baidu {
applicationId = "com.package.baidu"
manifestPlaceholders = [CHANNEL_VALUE: "234"]
}
}
对比上面的示例代码, 我们增加了applicationId 字段的配置, 这个字段即为修改相应渠道包的packageName. (关于,applicationId 与 packageName的具体区别, 参见[http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename])
这里满足了不同渠道打出不同包名的apk, 下面介绍不同渠道打出不同应用名的apk的步骤(指定不同的图标同理, 本文不展开介绍)
指定不同的应用名, 相对而言会复杂一点, 因为gradle里没有对此字段进行支持(android:label字段),所以需要我们利用脚本去动态的修改此字段。这里, 我们以上面wandoujia渠道为里, 如果它需要将应用名改为指定的, 那么我们就需要在原来的AndroidManifest.xml里面去修改Application项的android:label字段。
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['jni', 'src']
...
}
wandoujia{
manifest.srcFile 'WDJ_AndroidManifest.xml'
}
...
}
修改一个渠道对应的AndroidManifest.xml(或者其他的源文件)路径, 是在sourceSets{ }代码块里定义的。如上代码所示。这样, 在打包wandoujia渠道的时候, gradle就会自动去引用工程根目录下的WDJ_AndroidManifest.xml. (但它不是简单的直接使用此文件,而是将改文件与原始的AndroidManifest.xml进行Merge, 所以如果我们直接去修改WDJ_AndroidManifest.xml里的android:label字段, 而在原始的AndroidManifest.xml里也包含此字段的话, 那么就会产生冲突, 打包就会失败, 报错如下)
里面有句Suggestion, 即gradle给出的建议, 意思是让我们在Application项里添加, tools:replace=”android:label”。 也就是说, 如果我们想自定义在打包的时候去替换manifest某个字段时, 需要将该字段申明为 replace的。那么下面我们就需要用脚本去做帮忙做这件事了。
关于Manifest Merge的细节可见, http://developer.android.com/tools/building/manifest-merge.html
cp AndroidManifest.xml WDJ_AndroidManifest.xml
sed -i 's/旧应用名/新应用名/' WDJ_AndroidManifest.xml
sed -i '/ WDJ_AndroidManifest.xml
sed -i '/ WDJ_AndroidManifest.xml
第一句, 即复制出一个新的AndroidManifest文件;
第二句, 在WDJ_AndroidManifest.xml 替换新的应用名
第三句, 在manifest根部, 添加xmlns:tools=”http://schemas.android.com/tools”(这个是引入tools包)
第四句, 在application项里, 添加tools:replace=”android:label”
由此便完成了, 所有的工作, 下面只需要在 shell脚本最后, 添加./gradlew assembleRelease即可完成我们所需要的自定义自动化打包了, 满足了 多渠道, 不同渠道指定不同包名, 不同渠道指定不同应用名的需求。
最后附上,gradle官方教程
https://docs.gradle.org/current/userguide/userguide_single.html#sec:special_feature_of_gradle