杨子刚的博客


Android Product Flavors编译参数配置

2016-03-21

Android Studio 每一个项目(project)可以包含若干个模块(module),每个模块又可以配置若干个产品(product flavors)。使用product flavors可以以同一套代码为基础,编译出不同的apk。国内有着众多的安卓应用市场,一般情况下需要为每个市场提供的apk包都是不一样的(apk包里面包含有该市场的信息,以便统计哪个市场下载量大),product flavors可以很好的满足这个场景。

在此我们以模块app为例,如果我们想让app这个模块输出不同的apk,我们需要修改app/build.gradle这个文件。

假设我们需要提供两个apk:一个是演示版本;一个是发布版本。演示版本的第一个界面显示“演示版本”四个字,发布版本的第一个界面显示“发布版本”四个字。下面是修改后的app/build.gradle文件

 1 apply plugin: 'com.android.application'
 2 
 3 android {
 4     compileSdkVersion 23
 5     buildToolsVersion "23.0.2"
 6 
 7     defaultConfig {
 8         applicationId "com.ingphone.productflavors"
 9         minSdkVersion 14
10         targetSdkVersion 23
11         versionCode 1
12         versionName "1.0"
13     }
14     buildTypes {
15         release {
16             minifyEnabled false
17             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18         }
19     }
20 
21     productFlavors {
22         demo {
23             applicationId "com.ingphone.demo"
24             buildConfigField 'String','hello_text', "\"演示版本\""
25         }
26 
27         publish {
28             buildConfigField "String", "hello_text", "\"发布版本\""
29         }
30     }
31 
32 dependencies {
33     compile fileTree(dir: 'libs', include: ['*.jar'])
34     testCompile 'junit:junit:4.12'
35     compile 'com.android.support:appcompat-v7:23.4.0'
36     compile 'com.android.support:design:23.4.0'
37 }

从21行到30行为product flavors配置,我们定义了名为hello_text的buildConfigField。 接下来我们就可以在java代码里通过BuildConfig.hello_text来访问这个字符串变量。

buildConfigField是一个函数:

void buildConfigField(String type, String name, String value)

通过buildConfigField定义属性时,该属性会被展开为

public static final <type> <name> = <value>;

比如:

buildConfigField "String", "hello_text" "演示版本"

展开后为:

//BuildConfig.java
//BuildConfig.java由gradle自动生成
public static final String hello_text = 演示版本;

可以看到,gradle只是简单的把引号去掉,当定义String类型的属性时,就无法编译通过, 这时候就需要我们自己填上字符串的引号。

//build.gradle配置
buildConfigField "String", "hello_text" "\"演示版本\""
//展开后
public static final String hello_text = "演示版本";

在productFlavors中可以定义的属性以及可以调用的方法可以参考ProductFlavor。 在此列出一些常用的可配置项:

applicationId
versionCode
versionName
proguardfile
proguardfiles
targetSdkVersion
minSdkVersion

在编译时,可以在Build Variants中选择Build Variant,以决定到底是对哪一个product flavor进行编译,如下图:

也可以一次性的把所有的apk编译出来,只要双击下图中选中的assemble即可,生成的apk位于app/build/outputs/apk目录下:

Product Flavor特定代码

除了可以在build.gradle中指定不同的配置外,还可以对不同的product flavor指定不同的java源文件、res等等。 在此展示一下如何为不同的product flavor指定不同的java源文件。

对于模块app来说,java源代码主文件夹位置为app/src/main/java,对于模块下面的product flavor demo,针对demo特有的java源代码文件放在 app/src/demo/java,publish的java源代码文件放在app/src/publish/java。在示例项目中,我们定义了一个com.ingphone.productflavors.FlavorTest.java类。 该类的outputFlavor()函数在demo下会输出Demo flavor.,在publish下会输出Publish flavor.

demo:

publish:

示例项目:HelloProductFlavors