Android(安卓)Gradle
前言
Android应用程序使用开源的Gradle构建系统来构建。Gradle是在Java世界中广泛使用的、易定制化的现代化API。Android的Gradle插件针对Android应用程序添加了大量的特性,包括构建类型(build type)、定制(product flavor)、签名管理(signing configuration)、库项目(library project)等。
学习资料
- Gladle用户指南
- Android Studio 构建指南
- Android Studio Gradle,插件使用指南
- Gradle DSL语言API
- 跟我学Gradle「中文版」
参数说明
Setting.gradle
include ':app'
include语句表示app子目录是唯一的子项目。如果你添加一个Android库项目,其也会被添加到这个文件。
build.gradle
你可以在构件文件顶层添加所有子项目或模块通用的配置选项。
buildscript { repositories { jcenter() maven { url 'https://dl.google.com/dl/android/maven2/' } } dependencies { classpath 'com.android.tools.build:gradle:3.0.1' // 注意:不要把你的应用程序依赖放在这里;它们属于各独立模块的build.gradle文件。 }}allprojects { repositories { jcenter() }}task clean(type: Delete) { delete rootProject.buildDir}
Gradle的安装本身默认不包含Android的功能。Google为Gradle提供了一个Android的插件,其简化了Android项目的配置。构建文件顶层的buildscript块告诉Gradle去哪下载这个插件。
正如你看到的,默认这个插件会从jcenter下载,即Bintray JCenter Artifactory库。也支持其他的库(特别是mavenCentral(),默认的Maven仓库),但是JCenter现在已经成默认的了。JCenter中的内容都使用HTTPS连接并通过CDN来提供,同时也更快速。
allprojects段顶层项目和所有子项目都默认使用jcentrer()仓库来下载所有的Java第三方依赖库。
Gradle允许你自定义你自己的task,并插入到有向无环图(Directed Acyclic Graph,DAG),Gradle用其解析task之间的关系。这里一个clean task被添加到了构建的顶端。type: Delete
表示这个新的task是Gradle内置的Delete task的一个自定义实例。在这个例子中,这个task将构建目录从根项目中删除,默认构建目录即顶层中的build。
build.gradle[app]
apply plugin: 'com.android.application'android { // 前两个都应该被赋予最新可用的版本,因为他们都是向后兼容的,并且包含了所有当前的漏洞修复。 compileSdkVersion 27 // 目标编译环境 buildToolsVersion '26.0.2' // 构建工具的版本 defaultConfig { // 应用程序的“package”名字,在Google Play中应该是唯一的。 // 这个值在你的应用程序的整个生命周期都不能被改变。 // 改变这个值会使你的应用程序被认为是一个全新的应用程序,也就没法更新。 // 这个值是Android Manifest根元素下的一个package的属性。 applicationId "link_work.elderlycommunity" // 应用程序支持的最小版本 minSdkVersion 19 // 应用程序目标的Android版本。如果该值没有被设置为最新版本, // Android Studio会发出警告。 targetSdkVersion 27 // 版本号 versionCode 1 // 字符串,发行版本 versionName "1.0" flavorDimensions "versionCode" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } // 表示app期望使用的SDK版本 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } // APP签名,密钥创建过程请看下文。 signingConfigs { config { // 用户名 keyAlias 'androiddebugkey' // 密码 keyPassword 'android' // 秘钥保存地址 storeFile file('./debug.jks') // 存储密码 storePassword 'android' } } // 编译类型,详情请看下文。 buildTypes { debug { minifyEnabled false useProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguardTest-rules.pro' signingConfig signingConfigs.config // 调用签名 } release { minifyEnabled true useProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguardTest-rules.pro' } }}dependencies { // 依赖库}
targetSdkVersion
目标版本的设定值告知Android,应用是为哪一个API级别设计的。大多数情况下,目标版本就是最新发布的Android版本。
什么时候修改目标SDK版本?新发布的SDK版本会改变应用在设备上的显示方式,甚至连操作系统后台运行行为都会受到影响。如果应用开发完成,应确认它在新版本上能否如期那样运行。
降低SDK目标版本可以保证的是,即便在高于目标版本的设备上,应用仍然可以正常运行,且运行行为仍和目标版本一致。这是因为新发布版本中的变化已被忽略。
签名
查看签名
进入.android
文件夹,可以查看当前已经创建的keystore
。
使用keytool -list -keystore debug.keystore
可以查看keystore
的内容。
生成签名文件
生成指令为:keytool -genkey -v -keystore myApp.keystore -alias China -keyalg RSA -keysize 2048 -validity 10000
创建一个用RSA算法加密,大小为2KB,使用SHA256进行签名,10000天的有效期的密钥。
// APP签名signingConfigs {config {// 用户名keyAlias 'androiddebugkey'// 在签发过程中使用一个特定密钥的密码keyPassword 'android'// 秘钥保存地址storeFile file('./debug.jks')// 密钥库文件自身使用的密码storePassword 'android'}}
编译类型
// 编译类型buildTypes {debug {minifyEnabled falseuseProguard falseproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguardTest-rules.pro' signingConfig signingConfigs.config // 调用签名 } release { minifyEnabled true useProguard true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' testProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguardTest-rules.pro' } }}
参数 | 说明 |
---|---|
minifyEnabled | 代表在打包的时候app包自动删除无用的资源。如果设置为true,Gradle还会删除无须用到的依赖库。这只会在shrinkResource属性同时设置为true的时候才会生效。 |
shrinkResource | 见上。 |
useProguard | 开启混淆。 |
proguardFiles | 混淆文件规则。 |
资源分包
你也许遇到过一种情况,当你的APP写到一定程度的时候,你的layout文件和drawable文件会非常的多,这个时候,你可能就想要对资源文件进行分包。
首先,我们可以在app.gradle
增加如下内容:
android { sourceSets { main { // 配置res文件夹 res.srcDirs = [ 'src/main/res/layout/activity', 'src/main/res/layout/fragment', 'src/main/res/layout/ui', 'src/main/res/layout', 'src/main/res/drawable/img', 'src/main/res/drawable/xml', 'src/main/res/drawable', 'src/main/res' ] } }}
需要注意的是,目录的顺序需要从最里到最外(即父文件夹放在最后)。
分包结果如下:
说明
./gradlew
是在Gradle工程下,如果本地配置了gradle环境,可以使用gradle
。一般建议使用Gradle工程目录下的./gradlew
,防止版本问题。
参数 | 说明 |
---|---|
-i | Gradle默认不会输出很多信息,你可以使用-i选项改变日志级别为INFO |
-s | 如果运行时错误发生打印堆栈信息 |
-q | 只打印错误信息 |
-?-h,–help | 打印所有的命令行选项 |
-b,–build-file | Gradle默认执行build.gradle脚本,如果想执行其他脚本可以使用这个命 |
令,比如gradle -b test.gradle | |
–offline | 在离线模式运行build,Gradle只检查本地缓存中的依赖 |
-D,–system-prop | Gradle作为JVM进程运行,你可以提供一个系统属性比如:-Dmyprop=myValue |
-P,–project-prop | 项目属性可以作为你构建脚本的一个变量,你可以传递一个属性值给build脚本,比如:-Pmyprop=myValue |
task | 显示项目中所有可运行的任务 |
properties | 打印项目中所有可配置的属性值 |
显示任务
检查构建脚本,并显示所有的任务:./gradlew -q task
任务名称缩写
Gradle支持命令行输入任务名的驼峰简写:
task groupTherapy << { ...}task generateTests << { ...}
这个时候输入./gradlew gT
会报错,因为存在两个简写一致的情况。
排除一个任务
参数-x用于排除一个任务:./gradlew groupTherapy -x yayGradle0
构建项目
开始构建项目:./gradlew build
命令
包装器
Gradle包装器,包装器是Gradle的一个核心特性,它允许你的机器不需要安装运行时就能运行Gradle脚本,而且她还能确保build脚本运行在指定版本的Gradle。它会从中央仓库中自动下载Gradle运行时,解压到你的文件系统,然后用来build。终极目标就是创建可靠的、可复用的、与操作系统、系统配置或Gradle版本无关的构建。
task wrapper(type: Wrapper) { gradleVersion = '1.7'}
然后执行这个任务:gradle wrapper
。
记住你只需要运行gradle wrapper
一次,以后你就能用wrapper来执行你的任务,下载下来的wrapper文件会被添加到版本控制系统中。如果你的系统中已经安装了Gradle运行时,你就不需要再添加一个gradle wrapper
任务,你可以直接运行gradle wrapper
任务,这个任务会使用你的Gradle当前版本来生成包装文件。
项目
Project实例允许你访问你项目所有的Gradle特性,比如任务的创建和依赖了管理,记住一点当访问你项目的属性和方法时你并不需要显式的使用project变量–Gradle假定你的意思是Project实例,比如setDescription("myProject")
。
外部属性
外部属性一般存储在键值对中,要添加一个属性,你需要使用ext命名空间。
project.ext.myProp = 'myValue'ext { someOtherProp = 123}
相似的,外部属性可以定义在一个属性文件gradle.properties
中:
exampleProp = myValuesomeOtherProp = 455
我们可以在项目中直接访问这两个变量:
assert project.exampleProp == 'myValue'task printGradleProperty << { println "Second property: $someOtherProp"}
任务
动作就是你在任务里面放置构建逻辑的地方,Task接口中提供了两个方法来声明任务的动作:doFirst
和doLast
,当任务执行的时候,定义在闭包里面的动作逻辑就按照顺序执行。
version = '0.1-SNAPSHOT'task printVersion { doFirst { println "Version: $version" } doLast { println "Version: $version" }}
Gradle的生命周期
- 初始化
- 配置
- 执行
Android Studio使用
下面放上一些比较常见的Android Studio的Gradle使用方式。
多线程编译
在项目根目录中创建gradle.properties,加入以下配置
org.gradle.daemon=trueorg.gradle.parallel=true
解决依赖问题和编译
- 打印依赖树:
gradle dependencies
- 编译:
gradle build
- 编译查看详细信息:
gradle build --stacktrace
Manifest merger failed with multiple errors
通过以下命令,可以找出问题所在:
- Mac and Linux:
./gradlew processReleaseManifest --stacktrace
- Windows:
gradlew processReleaseManifest --stacktrace
附录
- Gradle Build Language Reference
- Declaring Dependencies
- Managing Dependency Configurations
书籍
- Gradle Recipes for Android
- [美国]Ken Kousen
- 《Android编程权威指南》
更多相关文章
- 在Android中使用Lua脚本 —— Programing Lua on Android
- android 游戏导引(1. 建立 OpenGL 项目)
- 【整理】android开源项目【tool篇】
- Eclipse ADT 创建Android项目----工程目录详解
- 高手速成android开源项目【tool篇】
- [Android]调试webview
- 【android】AsyncTask完全剖析(二)
- Android百度地图——定位SDK(版本v3.1)(一)
- 安卓系统框架介绍