ApplicationId 与 packageName
最后更新于:2022-04-01 02:26:30
# ApplicationId 与 PackageName
> 基于 [http://blog.csdn.net/maosidiaoxian/article/details/41719357](http://blog.csdn.net/maosidiaoxian/article/details/41719357) 校对整理,感谢原文作者 [貌似掉线](http://my.csdn.net/maosidiaoxian)
Android 应用都有自己的包名。包名是设备上每个应用程序的唯一标识,同样也是 Google Play 商店里的唯一标识。就是说,假如你已经使用某个包名来发布应用,**就不能再去改变应用的包名**,因为这样做会导致你的应用被视为一个全新的应用,你现有的用户也不会收到应用的更新通知。
旧版的 Android Gralde 构建系统中,应用的包名由 manifest 中根节点的 package 属性决定:
AndroidManifest.xml:
~~~
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.my.app"
android:versionCode="1"
android:versionName="1.0" >
~~~
然而,这里所定义的 package 还有另一个作用:用来命名资源类 R(以及用于解析相关的 Activity)。在上面的示例中,最终生成的 R 类为 **com.example.my.app.R**,所以如果你在其他包中的代码需要引用资源,对应的 .java 文件需要导入 `com.example.my.app.R`。
在新的 Android Gradle 构建系统中,你可以轻松地构建多个不同版本的应用。例如,你可以同时构建免费版和专业版的应用(使用 flavor),并且它们在 Google Play 上也应该要有不同的包名,这样它们就能够在同一设备上安装并且能够单独购买使用等等。同样的,你也可以构建 “debug”、“alpha”、“beta” 版的应用(使用 build type),它们也同样可以有唯一的包名。
同时,代码中引用的 R 类要保持不变;在构建不同版本的应用时,对应的(引用了 R 的) .java 源文件也不能改动。
因此,我们将包名的两种作用**解耦**:
- “application id” 对应 apk 中 manifest 定义的应用包名,同时用于设备以及 Google Play 的应用唯一标识。
- “package” 用于在源码中引用 R 类以及解析注册相关的 activity/service,对应 Java 的包名概念。
你可以在 Gradle 文件中指定 application id,如下所示:
app/build.gradle:
~~~
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "19.1"
defaultConfig {
applicationId "com.example.my.app"
minSdkVersion 15
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
...
~~~
像以前一样,你需要像前面的 AndroidManifest.xml 示例在 Manifest 中指定给代码用的 “package”。
**关键部分**:参照上面的做法,即能解耦 **applicationId** 和 **package**。意思是你能够完全自由地重构你的代码,改变用于 Activity 和 Service 的内部包,改变 Manifest 的 package,重构导入语句。这都不会影响到 app 的最终 id,app 的 id 对应 Gradle 文件中 applicationId 的值。
你可以通过以下的 Gradle DSL 方法来为不同的 flavor 和 build type 定义不同的 applicationId:
app/build.gradle:
~~~
productFlavors {
pro {
applicationId = "com.example.my.pkg.pro"
}
free {
applicationId = "com.example.my.pkg.free"
}
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
....
~~~
(在 Android Studio 中,你可以通过 Project Structure 图形化界面来进行这些配置。)
注意:出于兼容性考虑,如果**没有**在 build.gradle 文件中定义 applicationId,那么 applicationId 将默认为 AndroidManifest.xml 中所指定的 package 的值。在这种情况下,applicationId 和 package 显然未解耦,此时重构代码也将会更改应用的 id !在 Android Studio 中,新建的项目会指定这两个值。
注意:package 始终必须在默认 AndroidManifest.xml 文件中指定。如果存在多个 manifest(例如一个 flavor 有特定的 manifest 或一个 buildType 有特定的 manifest),package 可不指定,但如果被指定,必须和主 manifest 中指定的 package 完全相同。
附录
最后更新于:2022-04-01 02:26:28
# 闄勫綍
使用sourceCompatibility 1.7
最后更新于:2022-04-01 02:26:25
# 使用 sourceCompatibility 1.7
使用 Android KitKat(API 19 版本的 buildTools)就可以使用 diamond operator,multi-catch,strings in switches,try with resource等等(译注:都是 JDK7 的一些新特性,详情请参考 JDK7 文档)。设置为 1.7 版本,需要修改你的构建文件:
~~~
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
defaultConfig {
minSdkVersion 7
targetSdkVersion 19
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
~~~
你可以将 minSdkVersion 的值设置为 19 之前的版本,只是你只能使用除了 try with resources 之外的其它新语言特性。如果你想要使用 try with resources 特性,你就需要把 minSdkVersion 也设置为 19。
sourceCompatibility 1.7 需要 Gradle 使用 1.7 或者更高版本的 JDK(Android Gradle plugin 也需要 0.6.1 或者更高的版本)。
构建类型和产物定制的属性引用
最后更新于:2022-04-01 02:26:23
# 构建类型和产物定制的属性引用
Coming soon.
对于 Gradle 的 task(DefaultTask,JavaCompile,Copy,Zip),请参考 Gradle 文档。
> 译注:官方的 Coming soon。不是翻译 Coming soon `_(:зゝ∠)_`(话说 Android Studio 的 NDK 支持也 Coming soon 2年了)
操作 task
最后更新于:2022-04-01 02:26:21
# 操作 task
一般的 Java 项目中有一组有限的 task 用于互相处理并最终生成一个输出。
**classes** 是一个编译 Java 源代码的 task。
可以在 *build.gradle* 文件中通过脚本很容易使用 **classes** task。**classes** 是 **project.tasks.classes** 的缩写。
相比之下在 Android 项目中这就有点复杂。因为 Android 项目中会有大量相同的 task,并且它们的名字基于 *Build Types* 和 *Product Flavor* 生成。
为了解决这个问题,**android** 对象有三个属性:
- **applicationVariants**(只适用于 app plugin)
- **libraryVariants**(只适用于 library plugin)
- **testVariants**(app、library plugin 均适用)
这三个属性会分别返回一个 `ApplicationVariant`、`LibraryVariant` 和 `TestVariant` 对象的 [DomainObjectCollection](http://www.gradle.org/docs/current/javadoc/org/gradle/api/DomainObjectCollection.html)。
注意,使用这三个 collection 中的其中一个都会触发生成所有对应的 task。这意味着使用 collection 之后不需要更改配置。
`DomainObjectCollection` 可以直接访问所有对象,或者通过过滤器进行筛选。
~~~
android.applicationVariants.each { variant ->
....
}
~~~
这三个 variant 类都拥有下面的属性:
| 属性名 | 属性类型 | 说明 |
|-----|-----|-----|
| name | String | Variant 的名字,唯一 |
| description | String | Variant 的描述说明 |
| dirName | String | Variant 的子文件夹名,唯一。可能有不止一个子文件夹,例如 “debug/flavor1” |
| baseName | String | Variant 输出的基础名字,必须唯一 |
| outputFile | File | Variant 的输出,该属性可读可写 |
| processManifest | ProcessManifest | 处理 Manifest 的 task |
| aidlCompile | AidlCompile | 编译 AIDL 文件的 task |
| renderscriptCompile | RenderscriptCompile | 编译 Renderscript 文件的 task |
| mergeResources | MergeResources | 合并资源文件的 task |
| mergeAssets | MergeAssets | 合并 assets 的 task |
| processResources | ProcessAndroidResources | 处理并编译资源文件的 task |
| generateBuildConfig | GenerateBuildConfig | 生成 BuildConfig 类的 task |
| javaCompile | JavaCompile | 编译 Java 源代码的 task |
| processJavaResources | Copy | 处理 Java 资源的 task |
| assemble | DefaultTask | Variant 的标志性 assemble task |
`ApplicationVariant` 类还有以下附加属性:
| 属性名 | 属性类型 | 说明 |
|-----|-----|-----|
| buildType | BuildType | Variant 的 BuildType |
| productFlavors | List<ProductFlavor> | Variant 的 ProductFlavor,一般不为空但允许为空 |
| mergedFlavor | ProductFlavor | android.defaultConfig 和 variant.productFlavors 的组合 |
| signingConfig | SigningConfig | Variant 使用的 SigningConfig 对象 |
| isSigningReady | boolean | 如果是 true 则表明该 Variant 已经具备了所有需要签名的信息 |
| testVariant | BuildVariant | 将会测试该 Variant 的 TestVariant |
| dex | Dex | 将代码打包成 dex 的 task。如果该 Variant 是 Library,该值可为空 |
| packageApplication | PackageApplication | 打包最终 APK 的 task。如果该 Variant 是 Library,该值可为空 |
| zipAlign | ZipAlign | 对 APK 进行 zipalign 的 task。如果该 Variant 是 Library 或者 APK 不能被签名时,该值可为空 |
| install | DefaultTask | 负责安装的 task,可为空 |
| uninstall | DefaultTask | 负责卸载的 task |
`LibraryVariant` 类还有以下附加属性:
| 属性名 | 属性类型 | 说明 |
|-----|-----|-----|
| buildType | BuildType | Variant 的 BuildType |
| mergedFlavor | ProductFlavor | 只有 android.defaultConfig |
| testVariant | BuildVariant | 用于测试 Variant |
| packageLibrary | Zip | 用于打包 Library 项目的 AAR 文件。如果是 Library 项目,该值不能为空 |
`TestVariant` 类还有以下属性:
| 属性名 | 属性类型 | 说明 |
|-----|-----|-----|
| buildType | BuildType | Variant 的 Build Type |
| productFlavors | List<ProductFlavor> | Variant 的 ProductFlavor。一般不为空但允许为空 |
| mergedFlavor | ProductFlavor | android.defaultConfig 和 variant.productFlavors 的组合 |
| signingConfig | SigningConfig | Variant 使用的 SigningConfig 对象 |
| isSigningReady | boolean | 如果是 true 则表明该 Variant 已经具备了所有需要签名的信息 |
| testedVariant | BaseVariant | TestVariant 测试的 BaseVariant |
| dex | Dex | 将代码打包成 dex 的 task。如果该 Variant 是 Library,该值可为空 |
| packageApplication | PackageApplication | 打包最终 APK 的 task。如果该 Variant 是 Library,该值可为空 |
| zipAlign | ZipAlign | 对 APK 进行 zipalign 的 task。如果该 Variant 是 Library 或者 APK 不能被签名时,该值可为空 |
| install | DefaultTask | 负责安装的 task,可为空 |
| uninstall | DefaultTask | 负责卸载的 task |
| connectedAndroidTest | DefaultTask | 在连接设备上执行 Android 测试的 task |
| providerAndroidTest | DefaultTask | 使用扩展 API 执行 Android 测试的 task |
Android task 特有类型的 API:
- `ProcessManifest`
- `File manifestOutputFile`
- `AidlCompile`
- `File sourceOutputDir`
- `RenderscriptCompile`
- `File sourceOutputDir`
- `File resOutputDir`
- `MergeResources`
- `File outputDir`
- `MergeAssets`
- `File outputDir`
- `ProcessAndroidResources`
- `File manifestFile`
- `File resDir`
- `File assetsDir`
- `File sourceOutputDir`
- `File textSymbolOutputDir`
- `File packageOutputFile`
- `File proguardOutputFile`
- `GenerateBuildConfig`
- `File sourceOutputDir`
- `Dex`
- `File outputFolder`
- `PackageApplication`
- `File resourceFile`
- `File dexFile`
- `File javaResourceDir`
- `File jniDir`
- `File outputFile`
- 直接在 Variant 对象中使用 “outputFile” 可以改变最终的输出文件夹。
- `ZipAlign`
- `File inputFile`
- `File outputFile`
- 直接在 Variant 对象中使用 “outputFile” 可以改变最终的输出文件夹。
每个 task 类型的 API 都受 Gradle 的工作方式和 Android plugin 的配置方式限制。
首先,Gradle 中存在的 task 只能配置输入输出的路径以及部分可能使用的选项标识。因此,task 只能定义一些输入或者输出。
其次,这里面大多数 task 的输入都不是单一的,一般都混合了 *sourceSet*、*Build Type* 和 *Product Flavor* 中的值。保持构建文件的简洁和可读性,同时让开发者通过 DSL 修改这些对象来影响构建的过程,而不是深入修改输入和 task 的选项。
另外需要注意,上面的 task 中除了 ZipAlign 这个 task 类型,其它类型都要求设置私有数据来让它们运行。这意味着不能手动创建这些类型的新 task 实例。
这些 API 也可能会被修改。一般来说,目前的 API 是围绕着 task 的输入和输出入口来添加额外的处理(需要的时候)。欢迎反馈意见,特别是那些没有预见过的需求。
对于 Gradle 的 task(DefaultTask,JavaCompile,Copy,Zip),请参考 Gradle 文档。
dex 选项
最后更新于:2022-04-01 02:26:19
# dex 选项
~~~
android {
dexOptions {
incremental false
preDexLibraries = false
jumboMode = false
javaMaxHeapSize "2048M"
}
}
~~~
这将会影响到所有使用 dex 的 task。
aapt 选项
最后更新于:2022-04-01 02:26:16
# aapt 选项
~~~
android {
aaptOptions {
noCompress 'foo', 'bar'
ignoreAssetsPattern "!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~"
}
}
~~~
这将会影响所有使用 aapt 的 task。
Java 编译选项
最后更新于:2022-04-01 02:26:14
# Java 编译选项
~~~
android {
compileOptions {
sourceCompatibility = "1.6"
targetCompatibility = "1.6"
}
}
~~~
默认值是 “1.6” 。该设置将会影响所有需要编译 Java 源代码的 task。
构建选项
最后更新于:2022-04-01 02:26:12
# 鏋勫缓閫夐」
高级构建的自定义
最后更新于:2022-04-01 02:26:09
# 楂樼骇鏋勫缓鐨勮嚜瀹氫箟
多定制的变种版本
最后更新于:2022-04-01 02:26:07
# 多定制的变种版本
某些情况下,应用可能需要基于多个标准来创建多个版本。
例如,Google Play 中的 multi-apk 支持 4 种过滤器。根据每个过滤器来创建不同的 APK 需要使用 *Product Flavor* 分组。
假如有个游戏有免费版和付费版,并且需要在 multi-apk 支持中使用 ABI 过滤器(译注:ABI,应用二进制接口,优点是不需要改动应用的任何代码就能够将应用迁移到任何支持相同 ABI 的平台上)。该游戏应用需要 3 个 ABI 和两个特定版本,因此就需要生成 6 个 APK(忽略不同 *Build Types* 生成的 variant 版本)。
然而,3 个 ABI 付费版的源代码都是相同的,因此创建 6 个 flavor 来实现并不是一个好办法。
相反的,可以使用两个 flavor 分组,并且让它自动构建所有可能的 variant 组合。
对应的功能实现需要使用 Flavor Dimensions(译注:`Flavor Dimensions` 对应旧版中的 `Flavor Groups`),并将 flavor 分配到一个指定的 Group 中。
~~~
android {
...
flavorDimensions "abi", "version"
productFlavors {
freeapp {
flavorDimension "version"
...
}
x86 {
flavorDimension "abi"
...
}
}
}
~~~
**andorid.flavorDimensions** 数组按照先后排序定义了可能用到的分组。(示例中)每个 *Product Flavor* 都被分配到一个分组中。
示例中将 *Product Flavor* 分为两组,为别为 abi [x86,arm,mips] 和 version [freeapp,paidapp],再加上默认的 *Build Type* [debug,release],最后会生成以下的 Build Variant:
- `x86-freeapp-debug`
- `x86-freeapp-release`
- `arm-freeapp-debug`
- `arm-freeapp-release`
- `mips-freeapp-debug`
- `mips-freeapp-release`
- `x86-paidapp-debug`
- `x86-paidapp-release`
- `arm-paidapp-debug`
- `arm-paidapp-release`
- `mips-paidapp-debug`
- `mips-paidapp-release`
**andorid.flavorDimensions** 中元素的顺序非常重要(variant 命名和优先级等)。
每个 variant 版本的配置由几个 *Product Flavor* 对象决定:
- **android.defaultConfig**
- 一个来自 abi 组中的对象
- 一个来自 version 组中的对象
flavorDimensions 中的顺序决定了 flavor 的优先级,这对于资源来说非常重要,因为 flavor 中的值会替换定义在低优先级的 flavor 中的值。
flavor dimensions 使用最高的优先级定义,因此前面例子中的优先级为:
~~~
abi > version > defaultConfig
~~~
Multi-flavors 项目同样拥有额外的 sourceSet,类似于 variant 的 sourceSet,只是少了 Build Type:
- **android.sourceSets.x86Freeapp**位于 `src/x86Freeapp/`
- **android.sourceSets.armPaidapp**位于 `src/armPaidapp/`
- 等等...
这允许在 flavor-combination(组合 flavor)的层次上进行定制。它们拥有比最基本的 flavor 的 sourceSet 更高的优先级,但是优先级低于 Build Type 的 sourceSet。
测试
最后更新于:2022-04-01 02:26:05
# 测试
测试 multi-flavors 项目非常类似于测试简单的项目。
**androidTest** 的 *sourceSet* 用于定义所有 flavor 共用的测试,但是每一个 flavor 也可以有它特有的测试。
正如前面提到的,每一个 flavor 都会创建自己的测试 sourceSet:
- **android.sourceSets.androidTestFlavor1**位于 `src/androidTestFlavor1/`
- **android.sourceSets.androidTestFlavor2**位于 `src/androidTestFlavor2/`
同样的,它们也可以拥有自己的依赖关系:
~~~
dependencies {
androidTestFlavor1Compile "..."
}
~~~
这些测试可以通过主要的标志性 **deviceCheck** task 或者主要的 **androidTest** task(当 flavor 被使用的时候这个 task 相当于一个标志性 task)来执行。
每个 flavor 也拥有自己的 task 来执行测试:`androidTest<VariantName>`。例如:
- **androidTestFlavor1Debug**
- **androidTestFlavor2Debug**
同样的,每个 variant 版本也会创建对应的测试 APK 构建 task 和 安装或卸载 task:
- **installFlavor1Debug**
- **assembleFlavor1Test**
- **installFlavor1Test**
- **uninstallFlavor1Debug**
- ...
最终的 HTML 报告根据每个 flavor 的报告汇总而成。
下面是测试结果和报告文件的路径,每组第一个是每个 flavor 版本的结果,第二个是汇总结果:
- `build/androidTest-results/flavors/<FlavorName>`
- `build/androidTest-results/all/`
- `build/reports/androidTests/flavors<FlavorName>`
- `build/reports/androidTests/all/`
改变 report 或 results 的输出文件夹都只会改变对应的根目录,构建时仍会创建每个 flavor 的文件夹,并且仍会汇总测试结果以及报告文件。
构建和任务
最后更新于:2022-04-01 02:26:03
# 构建和任务
我们前面提到每一个 *Build Type* 会创建自己的 `assemble<name>` task,但是 *Build Variant* 是 *Build Type* 和 *Product Flavor* 的组合。
当使用 *Product Flavor* 的时候,将会创建更多的 assemble-type task。分别是:
1. `assemble<Variant Name>`允许直接构建一个 variant 版本,例如 **assembleFlavor1Debug**。
1. `assemble<Build Type Name>`允许构建指定 Build Type 的所有 APK,例如 **assembleDebug** 将会构建 `Flavor1Debug` 和 `Flavor2Debug` 两个 variant 版本。
1. `assemble<Product Flavor Name>`允许构建指定 flavor 的所有 APK,例如 **assembleFlavor1** 将会构建 `Flavor1Debug` 和 `Flavor1Release` 两个 variant 版本。
另外 **assemble** task 会构建所有的 variant 版本。
源组件和依赖
最后更新于:2022-04-01 02:26:00
# 源组件和依赖
与 *Build Type* 类似,*Product Flavor* 也会通过它们自己的 *sourceSet* 提供代码和资源。
上面的例子将会创建4个 *sourceSet*:
- **android.sourceSets.flavor1**位于 `src/flavor1/`
- **android.sourceSets.flavor2**位于 `src/flavor2/`
- **android.sourceSets.androidTestFlavor1**位于 `src/androidTestFlavor1/`
- **android.sourceSets.androidTestFlavor2**位于 `src/androidTestFlavor2/`
这些 *sourceSet* 用于与 **android.sourceSets.main** 和 *Build Type* 的 *sourceSet* 来构建 APK。
下面的规则用于处理所有的 sourceSet 来构建一个 APK:
- 多个文件夹中的所有的源代码(`src/*/java`)都会合并起来生成一个输出。
- 所有的 Manifest 文件都会合并成一个 Manifest 文件。类似于 *Build Type*,允许 *Product Flavor* 可以拥有不同的的组件和权限声明。
- 所有使用的资源(Android res 和 assets)遵循的优先级为 *Build Type* 会覆盖 *Product Flavor*,最终覆盖 **main***sourceSet* 的资源。
- 每一个 *Build Variant* 都会根据资源生成自己的 R 类(或者其它一些源代码)。Variant 互相之间没有什么是共享的。
最终,类似 *Build Type*,*Product Flavor* 也可以有它们自己的依赖关系。例如,如果使用 flavor 来生成一个基于广告的应用版本和一个付费的应用版本,其中广告版本可能需要依赖于广告 SDK,但是付费版不需要。
~~~
dependencies {
flavor1Compile "..."
}
~~~
在这个例子中,`src/flavor1/AndroidManifest.xml` 文件中可能需要声明访问网络的权限。
每一个 Variant 也会创建额外的 sourceSet:
- **android.sourceSets.flavor1Debug**位于 `src/flavor1Debug/`
- **android.sourceSets.flavor1Release**位于 `src/flavor1Release/`
- **android.sourceSets.flavor2Debug**位于 `src/flavor2Debug/`
- **android.sourceSets.flavor2Release**位于 `src/flavor2Release/`
这些 sourceSet 拥有比 Build Type 的 sourceSet 更高的优先级,并允许在 Variant 的层次上做一些定制。
产品定制的配置
最后更新于:2022-04-01 02:25:58
# 产品定制的配置
每一个 flavor 都是通过闭包来配置的:
~~~
android {
...
defaultConfig {
minSdkVersion 8
versionCode 10
}
productFlavors {
flavor1 {
packageName "com.example.flavor1"
versionCode 20
}
flavor2 {
packageName "com.example.flavor2"
minSdkVersion 14
}
}
}
~~~
注意 *ProductFlavor* 类型的 **android.productFlavors.*** 对象与 **android.defaultConfig** 对象的类型是相同的。就是说着它们拥有的属性是一样的。
**defaultConfig** 为所有的 flavor 提供基本的配置,每一个 flavor 都可以重写这些配置的值。在前面的例子中,最终的配置结果将会是:
- **flavor1**
- **packageName**: com.example.flavor1
- **minSdkVersion**: 8
- **versionCode**: 20
- **flavor2**
- **packageName**: com.example.flavor2
- **minSdkVersion**: 14
- **versionCode**: 10
通常情况下,*Build Type* 的配置会覆盖其它的配置。例如,*Build Type* 的 **packageNameSuffix** 会被追加到 *Product Flavor* 的 **packageName** 上面。
但有部分设置可以同时在 *Build Type* 和 *Product Flavor* 中设置。在这种情况下,按照个别为主的原则决定。
例如,**signingConfig** 允许通过设置 **android.buildTypes.release.signingConfig** 来为所有的 `release` 包共用相同的 *SigningConfig*。也可以通过设置 **android.productFlavors.*.signingConfig** 来为每一个 `release` 包指定它们自己的 *SigningConfig*。
构建类型+产品定制=构建变种版本
最后更新于:2022-04-01 02:25:56
产品定制
最后更新于:2022-04-01 02:25:53
# 产品定制
Product flavor 可定义应用的不同定制版本,一个项目可以同时定义多个不同的 flavor 来改变应用的输出。
不同定制版本之间的差异非常小的情况,可以考虑使用 Product flavor。虽然项目最终会生成多个定制版本,但是它们本质上都是同一个应用。这种做法可能是比使用 Library 项目更好的实现方式。
Product flavor 需要在 **productFlavors** 这个 DSL 容器中声明:
~~~
android {
....
productFlavors {
flavor1 {
...
}
flavor2 {
...
}
}
}
~~~
这里创建了两个flavor,名为 **flavor1** 和 **flavor2**。
> 注意:flavor 的命名不能与已存在的 *Build Type* 或者与 **androidTest** 的 *sourceSet* 有冲突。
构建 Variants(变种)版本
最后更新于:2022-04-01 02:25:51
# 构建 Variants(变种)版本
新构建系统的一个目标就是允许为同一个应用创建不同的版本。
这里有两个主要的使用情景:
1. 同一个应用的不同版本。例如一个免费的版本和一个收费的专业版本。
1. 同一个应用需要打包成不同的 apk 以发布 Google Play Store。[点击此处](http://developer.android.com/google/play/publishing/multiple-apks.html) 查看更多详细信息。
1. 综合 1 和 2 两种情景。
这个目标就是要让在同一个项目里生成不同的 APK 成为可能,以取代以前需要使用一个库项目和两个或以上的应用项目分别生成不同 APK 的做法。
Lint 支持
最后更新于:2022-04-01 02:25:49
# Lint 支持
> Lint 支持,译者注:Lint 是一个可以检查 Android 项目中存在的问题的工具
从 0.7.0 版本开始,你可以为项目中一个特定的 variant(变种)版本运行 lint,也可以为所有 variant 版本都运行 lint。它将会生成一个报告描述哪一个 variant 版本中存在着问题。
你可以通过以下 lint 选项配置 lint。通常情况下你只需要配置其中一部分,以下列出了所有可使用的选项:
~~~
android {
lintOptions {
// set to true to turn off analysis progress reporting by lint
quiet true
// if true, stop the gradle build if errors are found
abortOnError false
// if true, only report errors
ignoreWarnings true
// if true, emit full/absolute paths to files with errors (true by default)
//absolutePaths true
// if true, check all issues, including those that are off by default
checkAllWarnings true
// if true, treat all warnings as errors
warningsAsErrors true
// turn off checking the given issue id's
disable 'TypographyFractions','TypographyQuotes'
// turn on the given issue id's
enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
// check *only* the given issue id's
check 'NewApi', 'InlinedApi'
// if true, don't include source code lines in the error output
noLines true
// if true, show all locations for an error, do not truncate lists, etc.
showAll true
// Fallback lint configuration (default severities, etc.)
lintConfig file("default-lint.xml")
// if true, generate a text report of issues (false by default)
textReport true
// location to write the output; can be a file or 'stdout'
textOutput 'stdout'
// if true, generate an XML report for use by for example Jenkins
xmlReport false
// file to write report to (if not specified, defaults to lint-results.xml)
xmlOutput file("lint-report.xml")
// if true, generate an HTML report (with issue explanations, sourcecode, etc)
htmlReport true
// optional path to report (default will be lint-results.html in the builddir)
htmlOutput file("lint-report.html")
// set to true to have all release builds run lint on issues with severity=fatal
// and abort the build (controlled by abortOnError above) if fatal issues are found
checkReleaseBuilds true
// Set the severity of the given issues to fatal (which means they will be
// checked during release builds (even if the lint target is not included)
fatal 'NewApi', 'InlineApi'
// Set the severity of the given issues to error
error 'Wakelock', 'TextViewEdits'
// Set the severity of the given issues to warning
warning 'ResourceAsColor'
// Set the severity of the given issues to ignore (same as disabling the check)
ignore 'TypographyQuotes'
}
}
~~~
多项目报告
最后更新于:2022-04-01 02:25:47
# 多项目报告
在一个配置了多个应用项目和多个 Library 项目的多项目里,当同时运行所有测试的时候,只生成一个记录了所有测试报告的文件可能是非常有用的。
为了实现这个目的,需要在同一个依赖文件(译注:指的是使用 android gradle 插件的依赖文件)中添加另一个插件。可以通过以下方式添加:
~~~
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.6'
}
}
apply plugin: 'android-reporting'
~~~
必须添加在项目的根目录下,例如,与 *settings.gradle* 文件同级目录的 *build.gradle* 文件中。
之后,在命令行中进入项目根目录,输入以下命令就可以运行所有测试并合并所有报告:
~~~
gradle deviceCheck mergeAndroidReports --continue
~~~
> 注意:这里的 `--continue` 选项将允许所有测试,即使子项目中的任何一个测试运行失败都不会停止。如果没有这个选项,其中一个测试失败则会终止所有测试的运行,此时部分项目可能还未执行测试。