这一系列暂不更新,相关技术讨论,请移步微信群,谢谢,但愿你们多多支持!java
这是一个系列,因此若是你看完这篇文章,请看下列文章:android
Gradle for Android 第一篇( 从 Gradle 和 AS 开始 )segmentfault
Gradle for Android 第二篇( Build.gradle入门 )api
Gradle for Android 第三篇( 依赖管理 )微信
Gradle for Android 第五篇( 多模块构建 )app
Gradle for Android 第七篇( Groovy入门 )ide
当你在开发一个app,一般你会有几个版本。大多数状况是你须要一个开发版本,用来测试app和弄清它的质量,而后还须要一个生产版本。这些版本一般有不一样的设置,例如不一样的URL地址。更可能的是你可能须要一个免费版和收费版本。基于上述状况,你须要处理不一样的版本:开发免费版,开发付费版本,生产免费版,生产付费版,而针对不一样的版本不一样的配置,这极大增长的管理难度。工具
Gradle有一些方便的方法来管理这些问题。咱们很早以前谈过debug和release版本,如今咱们谈到另一个概念,不一样的产品版本。构建版本和生产版本一般能够合并,构建版本和生产版本的合并版叫作构建变种。学习
这一章咱们将学习构建版本,它能使得开发更有效率,而且学习如何使用它们。而后咱们会讨论构建版本和生产版本的不一样,以及如何将其合并。咱们会探讨签名机制,如何针对不一样的变种签名等。
在这一章,咱们遵循以下规则:
Build types
Product flavors
Build variants
Signing configurations
在Gradle的Android插件中,一个构建版本意味着定义一个app或者依赖库如何被构建。每一个构建版本都要特殊的一面,好比是否须要debug,application id是什么,是否不须要的资源被删除等等。你能够定义一个构建版本经过buildTypes方法。例如:
android { buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile ('proguard-android.txt'), 'proguard-rules.pro' } } }
这个文件定义了该模块是release版本,而后定义了proguard的位置。该release版本不是惟一的构建版本,默认状况下,还有个debug版本。Android studio把它视为默认构建版本。
当默认的构建版本不够用的时候,建立版本也是很容易的一件事,建立构建版本你只须要在buildTypes写入本身的版本。以下所示:
android { buildTypes { staging { applicationIdSuffix ".staging" versionNameSuffix "-staging" buildConfigField "String", "API_URL", "\"http://staging.example.com/api\"" } } }
咱们定义了一个staging版本,该版本定义了一个新的application id,这让其与debug和release版本的applicationID不一样。假设你使用了默认的配置,那么applicationID将会是这样的:
Debug: com.package
Release: com.package
Staging: com.package.staging
这意味着你能够在你的设备上安装staging版本和release版本。staging版本也有本身的版本号。buildConfigField定义了一个新的URL地址。你没必要事事都去建立,因此最可能的方式是去继承已有的版本。
android { buildTypes { staging.initWith(buildTypes.debug) staging { applicationIdSuffix ".staging" versionNameSuffix "-staging" debuggable = false } } }
initWith()方法建立了一个新的版本的同时,复制全部存在的构建版本,相似继承。咱们也能够复写该存在版本的全部属性。
当你建立了一个新的构建版本,Gradle也建立了新的source set。默认状况下,该文件夹不会自动为你建立,全部你须要手工建立。
app └── src ├── debug │ ├── java │ │ └── com.package │ │ │ ├── res │ │ └── layout │ │ └── activity_main.xml │ └── AndroidManifest.xml ├── main │ ├── java │ │ └── com.package │ │ │ ├── res └── MainActivity.java └── Constants.java │ │ │ │ │ │ │ └── AndroidManifest.xml ├── staging │ ├── java │ │ └── com.package ├── drawable └── layout └── activity_main.xml │ │ │ ├── res │ │ └── layout │ │ └── activity_main.xml │ └── AndroidManifest.xml └── release ├── java │ └── com.package │ └── Constants.java └── AndroidManifest.xml
注意:当你添加一个Java类的时候,你须要知道如下过程,当你添加了CustomLogic.java到staging版本,你能够添加相同的类到debug和release版本,可是不能添加到main版本。若是你添加了,会抛出异常。
当使用不一样的source sets的时候,资源文件的处理须要特殊的方式。Drawables和layout文件将会复写在main中的重名文件,可是values文件下的资源不会。gradle将会把这些资源连同main里面的资源一块儿合并。
举个例子,当你在main中建立了一个srings.xml的时候:
<resources> <string name="app_name">TypesAndFlavors</string> <string name="hello_world">Hello world!</string> </resources>
当你在你的staing版本也添加了rings.xml:
<resources> <string name="app_name">TypesAndFlavors STAGING</string> </resources>
而后合并的strings.xml将会是这样的:
<resources> <string name="app_name">TypesAndFlavors STAGING</string> <string name="hello_world">Hello world!</string> </resources>
当你建立一个新的构建版本而不是staging,最终的strings.xml将会是main目录下的strings.xml。
manifest也和value文件下的文件同样。若是你为你的构建版本建立了一个manifest文件,那么你没必要要去拷贝在main文件下的manifest文件,你须要作的是添加标签。Android插件将会为你合并它们。
咱们将在会以后的章节讲到合并的更多细节。
每个构建版本都有本身的依赖包,gradle自动为每个构建的版本建立不一样的依赖配置。若是你想为debug版本添加一个logging框架,你能够这么作:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' debugCompile 'de.mindpipe.android:android-logging-log4j:1.0.3' }
你能够结合不一样的构建版本着不一样的构建配置,就像这种方式,这让你的不一样版本的不一样依赖包成为可能。
和构建版本不一样,product flavors用来为一个app建立不一样版本。典型的例子是,一个app有付费和免费版。product flavors极大简化了基于相同的代码构建不一样版本的app。
若是你不肯定你是否须要一个新的构建版本或者product flavors,你应该问你本身,你是否须要内部使用和外部使用的apk。若是你须要一个彻底新的app去发布,和以前的版本彻底隔离开,那么你须要product flavors。不然你只是须要构建版本。
建立product flavors很是的容易。你能够在productFlavors中添加代码:
android { productFlavors { red { applicationId 'com.gradleforandroid.red' versionCode 3 } blue { applicationId 'com.gradleforandroid.blue' minSdkVersion 14 versionCode 4 } } }
product flavors和构建版本的配置不一样。由于product flavors有本身的ProductFlavor类,就像defaultConfig,这意味着你的全部productFlavors都分享同样的属性。
就像构建版本同样,product Flavors也有本身的代码文件夹。建立一个特殊的版本就像建立一个文件夹那么简单。举个例子,当你有的生产版本的blue flavors有一个不一样的app图标,该文件夹须要被叫作blueRelease。
在一些例子中,你可能须要建立一些product flavors的合并版本。举个例子,client A和client B可能都想要一个free和paid的版本,而他们又都是基于同样的代码,可是有不同的颜色等。建立四个不一样的flavors意味着有重复的配置。合并flavors最简单的作法多是使用flavor dimensions,就像这样:
android { flavorDimensions "color", "price" productFlavors { red { flavorDimension "color" } blue { flavorDimension "color" } free { flavorDimension "price" } paid { flavorDimension "price" } } }
当你添加了flavor dimensions,你就须要为每一个flavor添加flavorDimension,不然会提示错误。flavorDimensions定义了不一样的dimensions,固然其顺序也很重要。当你合并二个不一样的flavors时,他们可能有同样的配置和资源。例如上例:
blueFreeDebug and blueFreeRelease
bluePaidDebug and bluePaidRelease
redFreeDebug and redFreeRelease
redPaidDebug and redPaidRelease
构建变体是构建版本和生产版本的结合体。当你建立了一个构建版本或者生产版本,一样的,新的变体也会被建立。举个例子,当你有debug和release版本,你建立了red和blue的生产版本,那么变体将会有四个:
你能够在Android studio的左下角找到它,或者经过VIEW|Tool Windows|Build Variants打开它。该视图列出了全部的变体,而且容许你去切换它们。改变他们将会影响到你按Run按钮。
若是你没有product flavors,那么变体只是简单的包含构建版本,就算你没有定义任何构建版本,Android studio也会默认为你建立debug版本的。
android插件回味每个变体建立不一样的配置。一个新的Android项目会有debug和release版本,全部你可使用assembleDebug和assembleRelease,固然当你使用assemble命令,会两者都执行。当你添加了一个新的构建版本,新的task也会被建立。例如:
assembleBlue uses the blue flavor configuration and assembles both BlueRelease and BlueDebug.
assembleBlueDebug combines the flavor configuration with the build type configuration, and the flavor settings override the build type settings.
构建变体也能够有本身的资源文件夹,举个例子,你能够有src/blueFreeDebug/java/。
在打包app以前,Android插件会合并main中的代码和构建的代码。固然,依赖项目也能够提供额外的资源,它们也会被合并。你可能须要额外的Android权限针对debug变体。举个例子,你不想在main中申明这个权限,由于这可能致使一些问题,因此你能够添加一个额外的mainfest文件在debug的文件夹中,申明额外的权限。
资源和mainfests的优先级是这样的:
若是一个资源在main中和在flavor中定义了,那么那个在flavor中的资源有更高的优先级。这样那个在flavor文件夹中的资源将会被打包到apk。而在依赖项目申明的资源老是拥有最低优先级。
gradle让处理构建变体变得容易。
android { buildTypes { debug { buildConfigField "String", "API_URL", "\"http://test.example.com/api\"" } staging.initWith(android.buildTypes.debug) staging { buildConfigField "String", "API_URL", "\"http://staging.example.com/api\"" applicationIdSuffix ".staging" } } productFlavors { red { applicationId "com.gradleforandroid.red" resValue "color", "flavor_color", "#ff0000" } blue { applicationId "com.gradleforandroid.blue" resValue "color", "flavor_color", "#0000ff" } } }
在这个例子中,咱们建立了4个变体,分别是blueDebug,blueStaging,redDebug,redStaging。每个变体都有其不一样的api url以及颜色。例如:
忽略某个变体也是可行的。这样你能够加速你的构建当使用assemble的时候,这样你列出的tasks将不会执行那么你不须要的变体。你可使用过滤器,在build.gradle中添加代码以下所示:
android.variantFilter { variant -> if(variant.buildType.name.equals('release')) { variant.getFlavors().each() { flavor -> if (flavor.name.equals('blue')) { variant.setIgnore(true); } } } }
在这个例子中,咱们检查下:
你能够看到blueFreeRelease和bluePaidRelease被排除在外,若是你运行gradlew tasks,你会发现全部的关于上述变体的tasks再也不存在。
在你发布你的应用以前,你须要为你的app私钥签名。若是你有付费版和免费版,你须要有不一样的key去签名不一样的变体。这就是配置签名的好处。配置签名能够这样定义:
android { signingConfigs { staging.initWith(signingConfigs.debug) release { storeFile file("release.keystore") storePassword"secretpassword" keyAlias "gradleforandroid" keyPassword "secretpassword" } } }
在这个例子中,咱们建立了2个不一样的签名配置。debug配置是as默认的,其使用了公共的keystore和password,因此没有必要为debug版本建立签名配置了。staging配置使用了initWith()方法,其会复制其余的签名配置。这意味着staging和debug的key是同样的。
release配置使用了storeFile,定义了key alias和密码。固然这不是一个好的选择,你须要在 Gradle properties文件中配置。
当你定义了签名配置后,你须要应用它们。构建版本都有一个属性叫作signingConfig,你能够这么干:
android { buildTypes { release { signingConfig signingConfigs.release } } }
上例使用了buildTypes,可是你可能须要对每一个版本生成不一样的验证,你能够这么定义:
android { productFlavors { blue { signingConfig signingConfigs.release } } }
固然,你在flavor中定义这些,最好会被重写,因此最好的作法是:
android { buildTypes { release { productFlavors.red.signingConfig signingConfigs.red productFlavors.blue.signingConfig signingConfigs.blue } } }
在这一章,咱们讨论了构建版本和生产版本,以及如何结合它们。这将会是很是有用的工具,当你须要不一样的url以及不一样的keys,而大家有相同的代码和资源文件,可是有不一样的类型以及版本,构建版本和生产版本将会让你的生活更美好。
咱们也谈论了签名配置以及如何使用他们。
下一章,你将会学习到多模块构建,由于当你想把你的代码分红一个依赖包或者依赖项目的时候,或者你想把Android wear模块放在你的应用的时候,这将很是重要。