Gradle 之创建 Build Variants

什么是 Gradle

Gradle 是一个高级构建工具。


Gradle构建流程

图片来自于 Gradle 官网,根据官网介绍,上图从左往右,依次体现了:Build Anything >> Automate Everything >> Deliver Faster. 据此,我们可以看到它的主要特点:可以构建的种类多,自动化构建过程,快速交付。
Android Studio 就是使用了这种工具,来完成 APK 的打包过程。如上面所说,这个过程原本是自动化完成的。自动化的东西都是流水线,我们总会有一些自己的需求,这时,就需要自定义配置这个过程。
下面,主要讨论下构建变体的使用。

构建变体的需求

先来说一下这种需求。
通常,在开发环境中,我们会使用 debug 版本的应用;在发布是时候使用 release 版本。
在 debug 版本中个,我们会有显示日志的需求;在 release 版本中是不需要的,日志是为了方便我们调试,而且可能包含一些敏感数据。
在 release 版本中,通常我们需要进行代码混淆,否则,很容易被别人反编译,就像是一个人没有穿衣服,显然,debug 版本就不需要。
从应用功能上来讲,同一个 APP 在发布的时候,有时候会根据需要发布不同的版本,比如在不同的应用市场上会有一些定制,即使是在同一个市场上,可能也要提供付费版和免费版等等。

为了解决上述问题,不管是从构建方式的角度,还是应用功能差异性的角度构建 apk 包,我们都需要对这些版本进行管理。Gradle 就提供了这样一个途径,使得我们可以通过修改 构建配置(文件) 的方式以满足特定版本的需求,然后让 Gradle 根据我们的选择自动构建我们想要的应用。
当然,处理问题的方式不止一种,我们也会有很多替代方案。但是,明明离终点只差一步,为什么还要翻过一座大山呢?

什么是构建变体

谈完需求,下面我们来讲讲什么是构建变体,它是通过 BuildType 和 BuildFlavor 组合实现的。如下所示,共产生 6 个变体。

构建变体

所谓 BuildType 和 BuildFlavor,即构建类型和构建特征(或者叫产品风味)。

BuildType,构建类型,主要针对开发生命周期的不同阶段进行配置。一个模块或者项目,默认有两种类型,release 和 debug。 debug 类型下 debuggable 属性是 true,从而使得我们可以打断点进行调试。debug 类型在打包的时候,会使用默认的自动生成的签名,对于 release 类型来说,发布的时候需要使用我们自己的密钥进行签名。同时,我们还可以在发布的时候,进行代码混淆。

signingConfigs {
        release {
            storeFile file("xxxx.jks")
            storePassword "xxxx"
            keyAlias "xxxx"
            keyPassword "xxxx"
        }
    }
buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            applicationIdSuffix ".debug"
        }
        //这是自定义的 buildType,继承自 debug
        /*jnidebug {
            initWith debug
            applicationIdSuffix ".jnidebug"
            jniDebuggable true
        }*/
    }

BuildFlavor,构建特征,主要是用以发布给用户不同的应用版本。需要注意的是,这里的版本并非是版本号,而是功能。比如,我们上说所说的免费版、付费版。

 flavorDimensions "default"
    productFlavors {
        free {
            dimension "default"
            applicationIdSuffix ".free"
            versionNameSuffix "-free"
            buildConfigField "String", "NAME", "\"免费版\""
        }
        paid {
            dimension "default"
            applicationIdSuffix ".paid"
            versionNameSuffix "-paid"
            buildConfigField "String", "NAME", "\"付费版\""
        }
        cmpy {
            dimension "default"
            applicationIdSuffix ".cmpy"
            versionNameSuffix "-cmpy"
            buildConfigField "String", "NAME", "\"内部使用\""
        }
    }

如何使用构建变体

上一节,说了什么是构建变体,但是,我们该怎么使用以满足我们的需求呢?有两个地方,给我们带来了可能性:BuildConfig 和 SourceSet(源集)。

BuildConfig

也许你已经注意到了上面 productFlavor 中的

 buildConfigField "String", "NAME", "\"免费版\""

事实上,对于每一种变体,都会有一个 BuildConfig 与之一一对应。
我们来看看构建变体 free.debug 的BuildConfig:

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.ygs.test.free.debug";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "free";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0-free";
  // Fields from product flavor: free
  public static final String NAME = "免费版";
}

这些字段都是静态常量,在项目中,我们都可以通过 BuildConfig 直接访问。比如,你可以通过 BuildConfig.DEBUG 判断当前版本是否是 debug 版本;可以通过 BuildConfig.FLAVOR 判断当前的 productFlavor,已决定是否启用某个功能。当然,我们也可以自定义字段,比如:

 buildConfigField "String", "NAME", "\"免费版\""

上述这些字段,无论是自定义的,还是默认的,都可以成为我们在项目中的判断条件。

选择相应的构建变体打包
SourceSet

所以源集,即代码和资源的分组。这可能有点抽象,举个栗子,src/main 就是一个源集。
每个 buildType 可以有一个源集,每个 buildFlavor 可以有一个源集,每个 buildVariant 同样可以有一个源集。
其中,src/main 这个源集是所有源集所共有的,除此之外,源集之间互斥。

使用源集

如上图所示,一共有三个源集:freeDebug、freeRelease、main。
注意,freeDebug、freeRelease 实际上是使用 buildVariant 的构建的源集,需要和构建变体的名字一样(当然可以通过配置修改这种默认行为)。
这里有几点注意事项:

  • 对于 java 文件来讲,freeDebug 中不能出现和 main 中一样在同一个包下类名相同的 java 文件,因为他们之间是共享关系,相当于将 main 中的所有 java 和 freeDebug 合并在一起。如果出现两个相同名字的 java 文件,会报错。freeDebug 和 freeRelease 不同,它们所有的资源都是互斥的,相互不影响,因为我们在构建的时候,也只能选择其中一种进行构建。假设我们选择了 freeDebug,那么 freeRelease 就会被剔除在外。
  • 对于 res 文件夹下的这些资源文件,freeDebug 和 freeRelease 这些源集之间同样是互斥的,相互没有任何影响。但是对于不同源集和 main之间,却存在着资源合并或替换的情况。
    对于 drawable 及其相关文件夹下的图片而言,freeDebug 中的图片会直接覆盖 main 中的同名图片。对于 layout 文件夹下的布局文件也是这样。
    但是,对于 values 文件夹下的 xml 文件来说,确是文件内容的合并。比如在源集 main 中的 strings.xml 中
<resources>
<string name="app_name">App</string>
<string name="hello_world">Hello world!</string>
</resources>

在源集 freeDebug 中的 strings.xml 中

<resources>
<string name="app_name">FreeDebug</string>
</resources>

它们合并之后就是

<resources>
<string name="app_name">FreeDebug</string>
<string name="hello_world">Hello world!</string>
</resources>

最后,非常重要的一点,合并或者替换时会遵照优先级:
buildVariant > buildType > buildFlavor> main > 库依赖项

总结

通过 Gradle 创建 构建变体,等于说给了我们告知 Gradle 选择哪些 class 哪些资源编译打包成 apk 的权利,使我们的版本管理更加灵活,方便。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269