其使用的基本原理是Gradle的 manifest merger 功能,这个功能的主要用途是可以在运行时替换AndroidManifest.xml里面的内容,因为使用不一样的渠道(或者第三方发布市场),从而在AndroidManifest.xml写上不一样的渠道ID,而避免重复多余的工做,统一在gradle写.如在AndroidManifest.xml可能要写上如下代码:java
<meta-data android:name="TD_APP_ID" android:value="C3FE75F5BE72B521C04C55B62E4E5D19" /> <meta-data android:name="TD_CHANNEL_ID" android:value="${CHANNEL_NAME}" /> <meta-data android:name="com.amap.api.v2.apikey" android:value="dcc98525f96d4cd62f5d3006e7fea013" /> <meta-data android:name="channelname" android:value="${CHANNEL_NAME}" /> <meta-data android:name="channelid" android:value="${CHANNEL_ID}" />
那么针对 android:value的值咱们能够在gradle这样写:android
android{ ......... defaultConfig{ ......... manifestPlaceholders = [ CHANNEL_NAME : "官网", CHANNEL_ID : "l79000i4:ts5x38dl:kxi542in:l79000hu"] } }
manifestPlaceholders里的值能够有多个用","隔开, 上文提到的android:value的值就是在manifestPlaceholders 定义的值,至关于自定义了一个类型.api
而后使用productFlavors打出各个渠道的包:服务器
android{ .......... productFlavors.all { flavor -> flavor.manifestPlaceholders = [CHANNEL_NAME: name] } productFlavors { home { manifestPlaceholders = [CHANNEL_NAME: "官网", CHANNEL_ID: "l79000i4:ts5x38dl:kxi542in:l79000hu"] } samsung { manifestPlaceholders = [CHANNEL_NAME: "三星应用市场", CHANNEL_ID: "moi000qp:al80ssgp:kxi542in:moi000qj"] } oppo { manifestPlaceholders = [CHANNEL_NAME: "OPPO可可应用市场", CHANNEL_ID: "moi000qq:al80ssgp:kxi542in:moi000qk"] } meizu { manifestPlaceholders = [CHANNEL_NAME: "魅族flyme应用商店", CHANNEL_ID: "moi000qr:al80ssgp:kxi542in:moi000ql"] } } }
productFlavors.all中的写法代表了各个渠道的CHANNEL_NAME所对应的值是productFlavors 里面的子项的名字,如三星的samsung 也能够这样写:app
productFlavors { wandoujia {} baidu {} c360 {} uc {} productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } }
productFlavors.all实际上是能够不用写的,只不过上文的写法使用汉字标明了各个渠道的意思,一目了然.并且各个渠道除了CHANNEL_NAME, 还有CHANNEL_ID因此要添加了一个productFlavors.all
在productFlavors 的各个子项里能够自定义其applicationId、versionCode以及versionName等信息,以便打出不一样包名的apk.测试
批量修改生成的apk文件名gradle
def buildTime() { def date = new Date() def formattedDate = date.format('yyyyMMdd') return formattedDate } android { buildTypes { release { applicationVariants.all { variant -> variant.outputs.each { output -> if (output.outputFile != null && output.outputFile.name.endsWith('.apk') &&'release'.equals(variant.buildType.name)) { def apkFile = new File( output.outputFile.getParent(), "Mymoney_${variant.flavorName}_v${variant.versionName}_${buildTime()}.apk") output.outputFile = apkFile } } } } } }
经过这种方式咱们能够知道这个apk是哪一个版本的,哪一个渠道的,是哪天打的包等等, 例如生成的Mymoney_baidu_v9.5.2.6_20150330.apk.ui
定义不一样的通讯方式
在平时Android开发中会有生产和测试环境,在发布正式版本时能够经过如下方式:google
android { defaultConfig { buildConfigField("String", "URL_UPDATE", "\"http://api2.okzaijia.com.cn/\"") } productFlavors { google{ buildConfigField("String", "URL_UPDATE", "\"http://api2.okzaijia.com.cn/\"") } baidu{ buildConfigField("String", "URL_UPDATE", "\"http://api2.okzaijia.com.cn/\"") } } }
BuildConfig.java是Android Gradle自动生成的一个java类文件,没法手动编译,可是能够经过Gradle控制,也就是说他是动态可配置的.buildConfigField 一共有3个参数,第一个是数据类型,就是你定义的常量值是一个什么类型,和Java的类型是对等的,这里是String。第二个参数是常量名,这里是 API_SERVER_URL。第三个参数是常量值。如此定义以后,就会在BuildConfig.java中生成一个常量名为 API_SERVER_URL的常量定义。默认配置的生成是:编码
public final static String API_SERVER_URL = "http://test.flysnw.org/" 当是baidu和google渠道的时候生成的就是http://www.flysnow.org/了。这个常量能够在咱们编码中引用。在咱们进行打包的时候会根据Gradle配置动态替换。
通常渠道版本都是用来发布的,确定用的是生产服务器,因此咱们可使用批处理来搞定这个事情,而不用在一个个渠道里写这些配置。
productFlavors.all { flavor -> buildConfigField("String", "URL_UPDATE", "\"http://api2.okzaijia.com.cn/\"") }