Gradle的Android插件中有个BuildVariants的概念,其实简单来说其实就是buildTypes+productFlavors,buildType前面我们看到过了,主要就是debug和release的分别。而productFlavors就是我们用来打包不同版本app的主要方式。从字面意思来翻译指的就是不同的“产品特点”。
Android Studio会自动根据build.gradle 生成对应的BuildVariants。比如以下代码:
android {
productFlavors {
free {}
paid {}
}
}
如果需要在debug模式下运行程序,但是多渠道打包中需要切换,此时,可以在
此处进行修改。
productFlavors
android {
flavorDimensions("isfree", "channel")
productFlavors {
free {dimension "isfree"}
paid {dimension "isfree"}
googleplay {dimension "channel"}
wandoujia {dimension "channel"}
}
}
这里我们就可以看到,我们有两个维度,一个是是否免费,另一个是渠道,我们能够生成2*4=8种Flavor,并且每个Flavor都有debug和release,总共就有8种不同的APK。所以理论上来说通过组合Flavor,我们可以做到各种不同的分类。
在国外一般来说开发者不太需要去管渠道的问题,他们的App只需要发往GooglePlay就可以了,但是在中国,我们有众多的APK分发平台,我们的APK需要发往各种地方,在做APP统计的时候我们就需要在APK里写入一些特征变量,发送到统计平台,以区分不同的渠道,在过去用ant打包的时代,我们通常的做法就是用不同的渠道名来重复ant任务一遍一遍地打包。
如果用gradle:我们可以通过增加一个名为channel的dimension来给每一个渠道一个特殊标示,代码就是我们之前看到的。但是你可能会问,我怎么在统计的时候获取这个渠道名呢?其实很简单,Android Studio会为我们生成一个名叫BuildConfig的类,这个类有一些关于打包的静态变量,下面是一个示例:
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "me.zheteng.android.example";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "freeGoogleplay";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
public static final String FLAVOR_isfree = "free";
public static final String FLAVOR_channel = "googleplay";
}
其实不止是渠道,通过这个类我们还可以很方便地获得这个APK的各种信息。相信大家一眼就能看出来每个字段的意思。(我们甚至还可以自定义字段)。
如果渠道非常多,你也可以通过读配置文件的方式动态生成不同的flavors。
如果我每个flavor都有点特别呢?
有的时候我们每个flavor可能不只是一个渠道名这么简单,我的ICON可能给每个渠道的有所不同,我的包名也可能有所不同。所有这些,都可以直接在这个flavor中重新定义:
android {
productFlavors {
googleplay {
applicationId "me.zheteng.android.example.googleplay"
}
}
}
如果需要不同的源代码或资源文件,可以在app/src下新建一个名为“flavor名”的目录(这里就是googleplay)。也就是app/src/googleplay,然后这个目录下的结构和app/src/main中是一样的,打包的时候会优先使用当前flavor下的文件。
其他Gradle小技巧
Provider名称
我们知道Provider的authority是系统中全局唯一的,有时候我们要为不同的flavor将authority改成不同的,通过gradle你可以这样实现:
<provider
android:exported="true"
android:name="com.path.to.my.Provider"
android:authorities="${applicationId}.provider"/>
你问我Java代码中怎么获取?难道你忘了BuildConfig了嘛?
Manifest 占位符
有些SDK会把配置在Manifest文件中的meta信息里,而不同的flavor这个信息不一样,这是我们可以通过Manifest 占位符来实现:
<meta-data android:value="${UMENG_APPKEY}" android:name="UMENG_APPKEY"/>
android {
productFlavors {
googleplay {
applicationId "me.zheteng.android.example.googleplay"
manifestPlaceholders = [UMENG_APPKEY: "我的友盟KEY"]
}
}
}