WorkWithGradle
完整gradle文件
1.使用buildConfigField
the basic usage of gradle
buildConfigField
可以在pakagename
包下生成一个BuildConfig
类,其中包含buildConfigField
中声明的字段。
在未声明任何buildConfigField
的情况下,也会生成默认的BuildConfig
,其中包含:
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "net.funol.workwithgradle";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
也可以声明自己的buildConfigField
。同一字段在不同的buildTypes
中声明不同的值,可以在构建的不同版本中使用,加以区分它们。比如在release
版本中使用生产环境的host
,在debug
版本中使用测试环境的host
,发布的时候就可以免去手动修改造成的一些不必要的麻烦。当然用gradle也可以一键打包所有版本。
buildTypes {
debug {
......
buildConfigField "String", "HOST", '"https://debug.funol.net"'
buildConfigField "boolean", "isRelease", 'false'
buildConfigField "int", "versionCode", "${defaultConfig.versionCode}"
}
release {
......
buildConfigField "String", "HOST", '"https://release.funol.net"'
buildConfigField "boolean", "isRelease", 'true'
buildConfigField "int", "versionCode", "${defaultConfig.versionCode}"
}
}
productFlavors
2.使用一个product flavor定义了从项目中构建了一个应用的自定义版本。一个单一的项目可以同时定义多个不同的flavor来改变应用的输出。虽然最项目终生成了多个定制的版本,但是它们本质上都是同一个应用,这种做法是比使用库项目更好的实现方式。
通常情况下,我们会在不同的应用市场发布应用。为了区分这些应用市场,我们会修改工程中的某个参数然后将工程分别打包。这个工作简单,但是频繁修改会增大出错的概率,而且发布的市场比较多的时候,这会占用很大一部分时间。为了节省时间,我们可以使用productFlavors
,在不同的flavor中定制应用。
productFlavors {
official{
//更多的定制信息
......
versionName "1.0-official"
}
google {
......
versionName "1.0-google"
}
wandoujia {
......
versionName "1.0-wandoujia"
}
......
}
gradlew assembleRelease
就可以打包出flavor中的所有版本。输出路径为<ProjectFolder>\app\build\outputs\apk\
3.使用manifestPlaceholders
这样定义完成之后,执行有时候我们需要在AndroidManifest中使用不同的key来定制不同的版本,这时候可以使用manifestPlaceholders
来替换AndroidManifest中的值。
在AndroidManifest中需要替换值得地方声明${DEMO_VALUE}
<meta-data
android:name="DEMO_NAME"
android:value="${DEMO_VALUE}"/>
在gradle中使用manifestPlaceholders
即可将其替换
manifestPlaceholders = [DEMO_VALUE: "demo-value"]
manifestPlaceholders
的数据类型为Map
,如果要一次替换多个值,写法如下:
manifestPlaceholders = [DEMO_VALUE1: "demo-value1",
DEMO_VALUE2: "demo-value2"]
通常使用统计SDK的时候会对不同渠道的app加以区分,比如友盟统计在AndroidManifest
中的meta-data
声明不同的UMENG_CHANNEL
值来区分不同渠道。这时可以在productFlavors
中使用manifestPlaceholders替换meta-data
中的内容。如果使用flavor
的名字作为UMENG_CHANNEL
的值,可以统一声明。
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL: name]
}
有时会在buildTypes
中定义不同版本的app,在这些app中使用了不同的第三方sdk的key,发布的时候又需要分发到不同的渠道。这时可以在buildTypes
和productFlavors
混合使用manifestPlaceholders
来定制版本。
buildTypes {
debug {
......
manifestPlaceholders.putAll([
UMENG_APP_KEY : "55a4612067e58ebxxxxxxxxx"])
}
release {
......
manifestPlaceholders.putAll([
UMENG_APP_KEY : "55a45f2967e58e1xxxxxxxxx"])
}
toTest {
......
manifestPlaceholders.putAll([
UMENG_APP_KEY : "55a4612067e58ebxxxxxxxxx"])
}
}
......
productFlavors.all { flavor ->
flavor.manifestPlaceholders.putAll([
AMAP_API_KEY : "e86b3a2aa88d36b36322e58xxxxxxxxx",
UMENG_CHANNEL : name])
}
4.定制文件名
定制完成app之后我们会执行./gradlew assemble命令同一打包,如果这些版本都以默认文件名打包,结果就会是只输出一个apk文件,最先打包出来的都被覆盖掉了。所以,我们需要定制输出的apk文件名称。
下面一段代码可以定制出<buildType>_WorkWithGradle_v<1.0>_<yyyyMMddHHmm>_<flavorName>.apk
这样的文件名。
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
//获取文件夹路径
def path = getProjectDir().absolutePath;
//文件名规则 <buildType>_WorkWithGradle_v<1.0>_<yyyyMMddHHmm>_<flavorName>.apk
def fileName = "${variant.buildType.name}_WorkWithGradle_v${defaultConfig.versionName}_${buildTime()}_${variant.productFlavors[0].name}.apk"
//debug模式要经常编译,文件名定制为同一个
if (variant.buildType.name == 'debug') {
fileName = 'app-debug.apk'
}
if (outputFile != null && outputFile.name.endsWith('.apk')) {
output.outputFile = new File(path, fileName)
}
}
}
执行./gradlew assemble
命令即可将所有版本打包出来,如果要打包某个版本,执行./gradlew assembleRelease
即可打包出Release
的所有渠道版本。
要打包指定渠道的版本,执行./gradlew assembleGoogle
(以google为例)即可打包出Google渠道的所有Build版本。
要打包指定版本的指定渠道包,执行./gradlew assembleGoogleRelease
(以google的发布版为例)即可打包出Google渠道的Release版本。