为不同版本添加不同代码

在开发中,不同的版本通常有不同的代码功能。例如最常用的Log开关,在debug版本中会打印开发日志,而在release版本中是需要关闭的。因此,一般会有一个全局的变量开关,根据不同的版本设置不同的值。这一切在Gradle脚本的支持下,仅仅变成了一句配置。笔者以buildType为例,为不同的buildType添加不同的参数配置,代码如下所示。

  1. buildTypes {
  2. release {
  3. buildConfigField "boolean", "testFlag", "true"
  4. minifyEnabled true
  5. shrinkResources true
  6. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  7. }
  8. xys {
  9. buildConfigField "boolean", "testFlag", "false"
  10. signingConfig signingConfigs.xys
  11. applicationIdSuffix ".xys"
  12. }
  13. }

通过指定buildConfigField的三个参数——类型、名称、值,就可以将一个变量设置到不同的buildType中去。打开系统的BuildConfig类,可以看到不同buildType下对应的testFlag的值。该文件对应的路径为/项目/app/build/generated/source/buildConfig/(你也可以通过双击Shift进行快速查找),内容如图4.19所示。

为不同版本添加不同代码 - 图1 图4.19 Release的BuildConfig

BuildType为xys的BuildConfig类,如图4.20所示。

为不同版本添加不同代码 - 图2 图4.20 xys的BuildConfig

直接通过BuildConfig类,就可以获取到不同buildType所对应的值了。这里笔者演示的是boolean类型的变量,如果是String类型的变量,在写入字符串的时候,需要加入转义字符。

  1. buildConfigField "String", "myname", "\"abs\""

同时在设置变量的时候,甚至可以继续使用变量,例如以下代码。

  1. def param = ……
  2. buildConfigField "String", "param", "\"String.${param}.String\""

除了Java代码可以使用这种方式进行添加之外,资源文件同样可以进行分版本设置属性值。例如要给不同的版本设置不同的AppName,通过Gradle同样是仅仅一行配置即可实现。

在buildType的release和xys这两个Type中进行设置resValue,添加如下所示的代码。

  1. buildTypes {
  2. release {
  3. resValue("string", "app_name", "XYSAppRelease")
  4. buildConfigField "String", "myname", "\"abx\""
  5. minifyEnabled true
  6. shrinkResources true
  7. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  8. }
  9. xys {
  10. resValue("string", "app_name", "XYS")
  11. buildConfigField "String", "myname", "\"abs\""
  12. signingConfig signingConfigs.xys
  13. applicationIdSuffix ".xys"
  14. }
  15. }

同时在defaultConfig领域中添加默认的配置,代码如下所示。

  1. defaultConfig {
  2. applicationId "com.xys.gradletest"
  3. minSdkVersion 14
  4. targetSdkVersion 23
  5. versionCode 1
  6. versionName "1.0"
  7. resValue("string", "app_name", "XYSApp")
  8. }

在AndroidMainifest文件中,同样使用android:label="@string/app_name"来获取app_name,但是要注意的是,一定要把string.xml文件中的<string name="app_name">GradleTest</string>删掉,这样才能编译过。因为Gradle在编译过程中会将脚本中的配置和string.xml文件中的配置进行merge操作,如果同时存在两份相同的属性值,就会发生冲突。

经过上面的配置,就可以非常方便地给不同buildType的包设置不同的AppName了。

另外resValue配置的参数,不一定非要替换代码中的占位,还可以直接增加变量到R文件中。

  1. def buildTime() {
  2. return new Date().format("yyyy-MM-dd HH:mm:ss")
  3. }
  4. defaultConfig {
  5. resValue "string", "build_time", buildTime()
  6. }

在上面的代码中,笔者定义了一个buildTime方法,并赋值给自定义的build_time变量。这时候不需要在Java代码中增加变量,即可直接引用已经编译到R文件中的变量build_time,代码如下所示。

  1. Log.d("test", getString(R.string.build_time));
  2.  
  3. 01-11 11:33:41.161 27829-27829/com.xys.gradletest D/test: 2016-01-11 11:33:27