Android 的构建系统会编译应用资源和源代码,然后打包成apk。Android Studio 中使用gradle 来自动化执行和管理构建流程,同时也允许我们自定义构建配置。虽然我们编辑gradle 文件是通过Android Studio 完成的,但是gradle 和Android 插件是独立于Android Studio 的。如果要使用命令行工具来完成gradle 构建,可以参考这篇。
一. 构建过程
典型的应用构建流程包括以下步骤,
(1)编译器将源代码转换成dex(Dalvik Executable)文件,将其他所有内容转换成已编译资源。
(2)APK 打包器将dex 和已编译资源合并成单个APK 文件。
(3)APK 打包器使用调试或发布秘钥库来对APK 进行签名:
如果构建的是调试版应用,打包器会使用调试秘钥库签名应用,Android Studio 自动使用调试秘钥库配置新项目;
如果构建的是对外发布版应用,打包器会使用发布秘钥库签名应用,如何签名参见在 Android Studio 中签名应用。
(4)在生成最终APK 之前,打包器使用 zipalign 工具对应用进行优化,减少其在设备上运行时的内存占用。
流程可以参考官网的一张图:
image.png
二. 自定义构建配置
使用gradle 和Android 插件可以帮助我们完成以下几个方面的自定义构建,分别是:构建类型、产品风味、构建变体、清单条目、依赖项、签名、Proguard、拆分APK 等。稍后针对这些方面一一进行介绍。
1. 配置文件
若想要自定义构建配置,就要改变gradle 的一些配置文件,下面先来认识一下这些文件。针对构建配置,一个项目中我们主要关注以下文件:
image.png
(1)顶级构建文件
就是上图中的1号文件,位于项目的根目录,用于定义适用于项目中所有模块的配置,默认情况下,顶级构建配置文件使用buildscript{} 代码块来定义项目中所有模块公用的gradle 存储仓库和依赖项,
/**
* 这个块是用来为gradle 配置依赖和依赖仓库的,也就是说项目模块中使用的依赖不能在这配置,比如,这个块
* 为gradle 提供了Android plugin 的依赖,因为gradle 需要Android plugin 来构建应用
*/
buildscript {
/**
* repositories 块主要是配置gradle 下载依赖的仓库。这个配置支持远程仓库像JCenter, Maven Central, 以及Ivy等,
* 当然也可以使用本地仓库或者自己定义的远程仓库。
*/
repositories {
jcenter()
}
/**
* dependencies 块配置了gradle 所需的依赖,下面这行的意思就是为gradle 3.0.1 添加Android plugin作为classpath 依赖
*/
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
/**
* allprojects 块就是为项目中的所有模块配置需要使用的依赖,以及下载依赖的仓库,这些依赖包括第三方库、插件之类的。
* 这里配置的是所有模块都需要的依赖,如果不是所有模块都需要,那么可以把这个依赖放到模块级别的配置文件build.gradle中。新创建一个项目时,
* Android Studio 会默认配置JCenter 仓库,但是没有配置依赖项。
*/
allprojects {
repositories {
jcenter()
}
}
(2)模块级配置文件
图中的第二个文件,模块级 build.gradle 文件位于每个 <project>/<module>/
目录,用于配置适用于其所在模块的构建设置。我们自定义构建配置时,基本就是对这个文件的修改。
以下这个示例 Android 应用模块 build.gradle 文件概述了部分基本 DSL 元素和设置:
/**
* 最上面的这几行apply plugin 是配置模块要使用的gradle 插件
*/
apply plugin: 'com.android.application'
/**
* android{} 块包含了所有构建的选项
*/
android {
/**
* compileSdkVersion 表示用来编译项目的API 版本,这意味着我们的APP 可以使用这个版本及以下版本的API 功能
*
* buildToolsVersion 确定的是SDK build tools 的版本,包括命令行工具、gradle 要使用的编译器等,
* 这些build tools 要通过SDK Manager 来下载
*/
compileSdkVersion 26
buildToolsVersion "27.0.3"
/**
* defaultConfig{} 块包含了一些默认的设置以及可供所有构建变体使用的属性,同时还可以从构建系统动态的更改 main/AndroidManifest.xml
* 的一些属性,我们可以通过配置不同的产品风味来改变这些属性的值
*/
defaultConfig {
/**
* applicationId 标识了发布应用的唯一包名,
* 然而,源代码依然会依赖在main/AndroidManifest.xml 中定义的包的属性
*/
applicationId 'com.example.myapp'
// 定义运行APP 所需的最低API 版本
minSdkVersion 15
// 测试运行时指定使用的sdk的版本,主要针对当存在多个sdk版本时,优先使用的SDK版本
targetSdkVersion 26
// 版本号
versionCode 1
// 用户友好的版本名,一般应用看版本时看的都是这个
versionName "1.0"
}
/**
* buildTypes{} 块可以配置不同的构建类型,默认情况定义了两种类型:debug 和release,
* 虽然debug 类型没在文件中写,但已经定义好了并且包含了debug 工具和debug 签名证书,当然工程自动生成的配置可能
* 并不能满足我们的需求,所以要自己进行一些自定义配置,另外用户无法自定义为test的type,它已经被单元测试占用。
*/
buildTypes {
/**
* 默认情况下,Android Studio 配置的release 类型开启了代码压缩,使用了mifiyEnabled 和Proguard,
* proguar-rules.pro 就是Proguard 的规则配置文件
*/
release {
minifyEnabled true // Enables code shrinking for the release build type.
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
/**
* productFlavors{} 块是用来配置多种不同的产品风味,比如多渠道打包,
* 在这里可以覆盖defaultConfig{} 中定义的属性,下面这个例子就是定义了免费版和付费版的APP
*/
productFlavors {
free {
applicationId 'com.example.myapp.free'
}
paid {
applicationId 'com.example.myapp.paid'
}
}
/**
* splits{} 块是拆分只包含某些属性的apk,其作用是将当前配置的版本的apk分裂生成多个只包含指定属性的Apk,
* 目前google给我们提供了根据language, abi, density进行拆分。
*/
splits {
// Screen density split settings
density {
// Enable or disable the density split mechanism
enable false
// Exclude these densities from splits
exclude "ldpi", "tvdpi", "xxxhdpi", "400dpi", "560dpi"
}
}
}
/**
* dependencies{} 配置了模块级的依赖
*/
dependencies {
compile project(":lib")
compile 'com.android.support:appcompat-v7:27.0.2'
compile fileTree(dir: 'libs', include: ['*.jar'])
}
上面简单认识了一下build.gradle 构建文件,更多属性可以参考DSL 文档,以及下面介绍更多自定义配置时还会介绍。
(3)gradle.properties 文件
即图中的第5个文件,可以配置项目中的gradle 设置,
(4)local.properties 文件
图中第7 个文件,是为构建系统配置本地环境属性,例如 SDK 安装路径。由于该文件的内容由 Android Studio 自动生成并且专用于本地开发者环境,因此我们可以手动修改该文件。
(5)settings.gradle 文件
图中第6 个文件,settings.gradle 文件位于项目根目录,用于指示 Gradle 在构建应用时应将哪些模块包括在内。对大多数项目而言,该文件很简单,只包括以下内容:
include ‘:app’ // app 是模块名
不过,多模块项目需要指定应包括在最终构建之中的每个模块。
在对各个文件有了一个认识之后,下面具体的从几个方面介绍自定义构建配置:
2. 构建类型
构建类型定义gradle 在构建应用时使用的某些属性,通常针对开发生命周期不同阶段进行配置。比如debug 构建类型支持debug 构建选项、使用debug 秘钥签名应用,而release 构建类型则可压缩、混淆 APK 以及使用发布密钥签署 APK 进行分发。必须至少定义一个构建类型才能构建应用。自定义的构建类型需要在模块级build.gradle 文件android{} 块下的buildType{} 块
android {
...
defaultConfig {...}
buildType {
myType {
}
}
...
}
上面示例新建了一个名字为myType 的构建类型,注意自定义构建类型的名字不能以test开头,自定义构建类型可以配置很多属性,比较常用的如下表
image.png
明白了buildTypes 里面的属性和方法的作用,也就可以根据产品的需要自定义构建类型了。
3. 产品风味
产品风味意味着我们可以发布给用户的不同应用版本,例如免费和付费的应用版本。我们可以将产品风味自定义为使用不同的代码和资源,同时对所有应用版本共有的部分加以共享和重复利用。产品风味是可选项,所以要想配置产品风味必须手动创建配置代码。
创建产品风味与创建构建类型类似:只需将它们添加到 productFlavors {} 代码块并配置想要的设置即可。产品风味支持与 defaultConfig 相同的属性,这是因为 defaultConfig 实际上属于 ProductFlavor 类。这意味着,我们可以在 defaultConfig {} 代码块中提供所有风味的基本配置,每种风味均可更改任何这些默认值。
下面可以看看ProductFlavor 有哪些属性,有些属性(标绿的)的作用和上面介绍的buildTypes 的属性是相同的,这里就不再赘述
image.png
上面再介绍属性时多次提到产品风味维度(dimension),现在来具体看一下它是怎么回事,在某些情况下,可能需要组合多种产品风味的配置,可以使用gradle 的Android 插件创建产品风味组,称为产品风味维度。在构建应用时,gradle 会将定义的每个风味维度中的产品风味配置与构建类型配置组合来创建最终构建变体。gradle 不会组合属于相同风味维度的产品风味。
一般在android{} 块下,通过flavorDimessions 属性定义风味维度
android {
flavorDimensions "api", "mode"
productFlavors {
min23 {
dimension "api"
}
min18 {
dimension "api"
}
free {
dimension "mode"
}
pay {
dimension "mode"
}
}
buildTypes {
debug {
}
release {
}
}
}
上面的配置定义了两个维度“api” 和“mode”,api 维度包含两个风味,即min23 和min18;mode 维度包含free 和 pay。
Gradle 创建的构建变体数量等于每个风味维度中的风味数量与配置的构建类型数量的乘积。在 Gradle 为每个构建变体或对应 APK 命名时,属于较高优先级风味维度的产品风味首先显示,之后是较低优先级维度的产品风味,再之后是构建类型,比如上面的配置,会产生8 个构建变体
构建变体:[min23, min18] [free, pay] [debug, release]
APK:app - [min23, min18] - [free, pay] - [debug, release].apk
例:构建变体 min23freedebug 产生 app-min23-free-debug.apk
这里既然提到了构建变体,那么下面就介绍一下构建变体。
这一篇内容已经够长了,接下来的请看Gradle 构建(二)。
网友评论