在 Android Studio 构建的项目中,基于 Gradle 进行项目的构建,同时使用 Android DSL (Domain Specific Language 领域专用语言)进Android 项目的配置。而 Gradle 是基于 Groovy 脚本语言进行开发,想要熟练掌握gradle的配置就得了解Groovy的基础以及Android DSL等知识。这里只整理下android 项目中常用的配置,需要更深入了解可以Groovy去搜索相关知识以及官方文档。
Gradle 基本
用Android Studio新建一个项目的时候,默认生成一大堆关于gradle的东西,其中最重要的是一个build.gradle的文件,结构如下:
先看看项目下的build.gradle内容:
buildscript {
repositories {
google()
jcenter()
maven { url 'https://maven.aliyun.com/repository/google' }
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'//这行表示使用的gradle插件版本
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://maven.aliyun.com/repository/google' }
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
}
}
}
在 repositories {}脚本块中可以配置maven仓库,比如下面这两行表示使用国内阿里云仓库的镜像地址,可以加快某些仓库的加载速度
maven { url 'https://maven.aliyun.com/repository/google' }
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
Module下的build.gradle内容:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.administrator.gitapplication"
minSdkVersion 23
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
}
解读:
apply plugin::指定用的是哪个插件,开发中常见的值有:
'com.android.application':Android APP插件(打包得到的是.apk文件)
'com.android.library':Android库插件,当要创建一个库时使用(打包得到的是.aar文件)
'java':普通的java插件(打包得到的是.jar文件)
defaultConfig{}用来配置一些默认属性 ,sdk版本,apk版本等基本属性,更多的属性下面介绍
buildTypes {}给不同版本的apk配置属性,常见的release ,debug等,可以配合productFlavors来配置多渠道打包
dependencies {}仓库依赖
常见配置介绍
1.signingConfigs 签名配置
要发布一个APK是需要签名的。使用android studio 可以通过build窗口下Generate Signed Apk命令来生成秘钥和签名。但是每次这么太麻烦,不符合程序猿的风格,于是就可以在gradle中配置签名信息:
signingConfigs {
//可以根据不同需要配置不同的信息,在需要的地方引用即可
debug {
// 配置的这几行都是生成keystore时需要的
storeFile file("keystore.keystore")
storePassword "storePassword "
keyAlias "keyAlias "
keyPassword "keyPassword "
}
release {
storeFile file("keystore.keystore")
storePassword "storePassword "
keyAlias "keyAlias "
keyPassword "keyPassword "
}
}
配置完秘钥信息在buildTypes {}中使用
buildTypes {
debug{
signingConfig signingConfigs.debug
}
release {
signingConfig signingConfigs.release
}
}
这样在编译不同版本的apk时就会使用不同的keystore,或者不使用签名
但是这样配置签名信息不够安全,一些私密信息应该隐藏起来:
1.在项目的根目录下创建一个名为 keystore.properties 的文件,并包含以下信息:
storePassword=myStorePassword
keyPassword=myKeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation
2.在build.gradle 文件中,按以下步骤操作来加载 keystore.properties 文件(必须在 android 代码块之前):
//这几行代码是加载keystore.properties中的信息,在需要的地方使用
keystoreProperties 获取信息。
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
...
signingConfigs {
config {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
}
...
2.buildTypes {}配置
debug {
buildConfigField "boolean", "LOG_DEBUG", "true"//在BuildConfig文件中生成LOG_DEBUG字段
minifyEnabled false //是否运行混淆文件
zipAlignEnabled false//是否使用Zipalign优化
//Android SDK中含一个“zipalign”的工具,它能够对打包的应用程序进行优化
//在你的应用程序上运行zipalign,使得在运行时Android与应用程序间的交互更加有效率
debuggable true//能否进行debug
shrinkResources false // 移除无用的resource文件
signingConfig signingConfigs.debug//签名配置
}
release {
buildConfigField "boolean", "LOG_DEBUG", "false"
minifyEnabled true
zipAlignEnabled true
shrinkResources false // 移除无用的resource文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'//配置混淆文件
signingConfig signingConfigs.release//签名配置
}
在构建时,Gradle 将生成 BuildConfig 类,以便应用代码可以检查与当前构建有关的信息。可以使用 buildConfigField() 函数,将自定义字段添加到 Gradle 构建配置文件的 BuildConfig 类中,然后在应用的运行时代码中访问这些值。如下:
...
Log.i(TAG, BuildConfig.LOG_DEBUG);
3.使用的统一的版本号
在引入库的时候需要确定版本号,有时会因为版本号不同而产生问题,所以最好统一管理一些版本相关信息。在项目下的顶级 build.gradle增加ext代码:
buildscript {...}
allprojects {...}
//此块封装自定义属性并使其可供所有项目中的模块使用
ext {
// 以下是可以定义的属性类型的几个示例。
compileSdkVersion = 28
buildToolsVersion = "28.0.3"
//还可以使用它来指定依赖项的版本。
//模块之间的版本一致可以避免行为冲突。
supportLibVersion = "28.0.0"
...
}
在module的build.gradle中使用ext代码
android {
//使用以下语法访问在项目级别定义的属性:
// rootProject.ext.property_name
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
...
}
...
dependencies {
compile"com.android.support:appcompatv7:${rootProject.ext.supportLibVersion}"//groovy中的语法,双引号下执行 ${表达式}
...
}
4.与 manifest 共享属性
某些情况下,您可能需要同时在 manifest 和代码中声明相同属性 。如以下示例中所示,请在模块的 build.gradle
文件中定义一个属性并使其对 manifest 和代码均可用,而不必在多个位置更新相同的属性以反映更改。要了解详情
android {
defaultConfig {
def filesAuthorityValue = applicationId + ".files"
manifestPlaceholders =
[filesAuthority: filesAuthorityValue]
buildConfigField("String",
"FILES_AUTHORITY",
"\"${filesAuthorityValue}\"")
}
...
}
...
在 manifest 中,访问以下占位符:
<manifest>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${filesAuthority}"
android:exported="false"
android:grantUriPermissions="true">
...
</provider>
</application>
</manifest>
5.BuildVariants变体
buildTypes+productFlavors相结合,组成构建变体,buildTypes构建类型,主要就是debug(测试) ,release(线上)的分别。productFlavors产品口味,主要就是各种渠道版本。两个合体就会构建出不同的版本apk (总apk个数=构建类型个数*渠道个数).看图:
signingConfigs {
debug {... }
release {... }
}
productFlavors {
ziyou_001 {...}
huawei_021 {...}
}
可以通过productFlavors来改变某个风味的属性:
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name.split("_")[1]]
}
productFlavors.huawei_021 {
flavor -> flavor.manifestPlaceholders = [app_name: "xxxx"]
}
一次生成所有渠道包
打开命令行窗口,进入到工程的根目录下,输入
gradle assembleChinaProduceRelease
6.配置 DEX 选项
在 Gradle 将代码编译到 DEX 文件中时,使用以下属性可以缩短构建时间。
android {
...
dexOptions {
//设置可以同时启动的DEX进程的最大数量。
maxProcessCount 8
//设置dex操作的最大内存分配池大小。
javaMaxHeapSize "2g"
//使Gradle能够预先解决库依赖关系。
preDexLibraries true
}
}