赞
踩
首先在AndroidMainifest文件的Application节点下,创建如下所示的meta-date节点。
<meta-data
android:name="PRODUCT"
android:value="${CHANNEL_VALUE}"/>
其中”${CHANNEL_VALUE}”就是要进行替换的渠道占位符。
在项目的gradle脚本的android领域中,添加productFlavors领域,并增加定义的渠道名。同时,使用manifestPlaceholders指定要替换渠道占位符的值,代码如下:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
xys{
signingConfig signingConfigs.xys
}
}
productFlavors{
xiaomi{
manifestPlaceholders = [CHANNEL_VALUE:"XIAOMI"]
}
wandujia {
manifestPlaceholders = [CHANNEL_VALUE:"WANDUJIA"]
}
}
定义了两种不同的渠道,——xiaomi、wandoujia。每个渠道都将指定值赋给渠道占位符CHANNEL_VALUE。这样配置后,就完成了整个多渠道打包工作。生成的apk如下:
每个渠道包都有三种:debug、release(系统默认的两种buildType)和xys(自定义的buildType)。
熟悉groovy语言之后,可以对以上脚本进行优化:
productFlavors{
xiaomi{}
wandujia {}
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders=[CHANNEL_VALUE:name]
}
在生成渠道包名后,包的命名通常是默认命名,即app-渠道名-buildType.apk。
但是有时候我们需要自定义apk包名,这时就可以通过gradle脚本进行快速重命名,代码如下:
android {
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
xys{
signingConfig signingConfigs.xys
}
}
productFlavors{
xiaomi{}
wandujia {}
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders=[CHANNEL_VALUE:name]
}
applicationVariants.all{ variant->
variant.outputs.each { output ->
if (output.outputFile != null && output.outputFile.name.endsWith(".apk")) {
if ('release'.equals(variant.buildType.name)) {
def apkFile = new File(output.outputFile.getParent(),
"releaseApp_${variant.flavorName}_v${variant.versionName}.apk")
output.outputFile = apkFile
}
if ('xys'.equals(variant.buildType.name)) {
def apkFile = new File(output.outputFile.getParent(),
"xysApp_${variant.flavorName}_v${variant.versionName}.apk")
output.outputFile = apkFile
}
if ('debug'.equals(variant.buildType.name)) {
}
}
}
}
}
这段代码的意思是取出所有的生成的apk包,并判断其文件是否是apk、是否是release、xys版本。如果是,则重新命名为“buildType名App_渠道名_v版本号.apk”。如下:
因为debug类型没有进行重命名,所以它的apk包名还是以前的。
在开发中,不同的版本通常有不同的代码功能。例如最常用的Log开关,在debug版本中会打印开发日志,而在release版本中是需要关闭的。因此,一般会有一个全局的变量开关,根据不同的版本设置不同的值。这一切在gradle脚本的支持下,仅仅变成了一句配置。以buildType为例,为不同的buildType添加不同的参数配置,代码如下所示:
buildTypes {
release {
buildConfigField("boolean", "testFlag", "true")
minifyEnabled false
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
xys{
buildConfigField("boolean", "testFlag", "false")
signingConfig signingConfigs.xys
}
}
通过指定buildConfigField的三个参数——类型、名称、值,就可以将一个变量设置到不同的buildType中去。打开系统的BuildConfig类,可以看到不同的buildType下对应的testFlag的值。该文件对应的路径为/项目/app/build/generated/source/buildConfig/,内容如下:
public final class BuildConfig {
public static final boolean DEBUG = false;
public static final String APPLICATION_ID = "com.example.administrator.demo";
public static final String BUILD_TYPE = "release";
public static final String FLAVOR = "wandujia";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
// Fields from build type: release
public static final boolean testFlag = true;
}
public final class BuildConfig {
public static final boolean DEBUG = false;
public static final String APPLICATION_ID = "com.example.administrator.demo";
public static final String BUILD_TYPE = "xys";
public static final String FLAVOR = "wandujia";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
// Fields from build type: xys
public static final boolean testFlag = false;
}
如果是string类型的变量,在写入字符串的时候,需要加入转义字符。
buildConfigField("String", "testFlag", "\"abc\"")
也可以在设置变量的时候,继续使用变量,如下:
buildConfigField("String", "testFlag", "\"${param}\"")
def param = ···
除了java代码可以使用这种方式进行添加之外,资源文件同样可以进行分版本设置属性值。例如要给不同的版本设置不同的AppName,通过gradle同样是仅仅一行配置即可实现。
在buildType的release和xys这两个Type中进行设置resValue,添加如下所示代码:
buildTypes {
release {
resValue("string", "app_name", "AppRelease")
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
xys{
resValue("string", "app_name", "AppXys")
signingConfig signingConfigs.xys
}
}
同时在defaultConfig领域中添加默认的配置,代码如下:
defaultConfig {
applicationId "com.example.administrator.demo"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
resValue("string", "app_name", "App")
}
在AndroidMainfest文件中,同样使用android:label=”@string/app_name”来获取app_name,但是要注意的是,一定要把string.xml文件中的Demo删掉,这样才能编译过。因为gradle在编译过程中会将脚本中的配置和string.xml文件中的配置进行merge操作,如果同时存在两份相同的属性值,就会发生冲突。
另外resValue配置的参数,不一定非要替换代码中的占位,还可以直接增加变量到R文件中。
def buildTime() {
return new Date().format("yyyy-MM-dd HH:mm:ss")
}
defaultConfig {
resValue("string", "build_time", buildTime())
}
在上面的代码中,定义了一个buildTime方法,并赋值给自定义的build_time变量。这时候不需要在java代码中增加变量,即可直接引用已经编译到R文件中的变量build_time,代码如下:
Log.d("-->", getString(R.string.build_time));
打印结果:
01-08 22:51:50.403 19532-19532/com.example.administrator.demo D/-->: 2017-01-08 22:50:45
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。