Android Gradle (一)Gradle的Android插件入门

本文首发于微信公众号「后厂村码农」

相关文章
Gradle核心思想(一)为什么现在要用Gradle?
Gradle核心思想(二)Gradle入门前奏
Gradle核心思想(三)Groovy快速入门指南
Gradle核心思想(四)看似无用,实则重要的Gradle Wrapper
Gradle核心思想(五)通俗易懂的Gradle插件讲解
Gradle核心思想(六)自定义Gradle插件的三种方式

前言

Gradle核心思想这个系列中我尽量避免了Gradle和Android之间的关联,这是因为在了解Gradle的核心思想后,可以更好的理解Android Gradle,因此这里强烈建议先阅读Gradle核心思想系列。
Android Gradle或者Gradle for Android,实际上指的就是Gradle的Android插件,这一篇我们入个门。

1.什么是Gradle的Android插件

Gradle核心思想(五)通俗易懂的Gradle插件讲解这篇文章中我们知道,Gradle有很多插件,为了支持Android项目的构建,谷歌为Gradle编写了Android插件,新的Android构建系统就是由Gradle的Android插件组成的,Gradle是一个高级构建工具包,它管理依赖项并允许开发者自定义构建逻辑。Android Studio使用Gradle wrapper来集成Gradle的Android插件。需要注意的是,Gradle的Android插件也可以独立于AndroidStudio运行。
Android的官方网站提到了新的Android构建系统主要有以下几个特点:

  • 代码和资源易于重用
  • 无论是针对多个apk发行版还是针对不同风格的应用程序,都可以很容易创建应用程序的多个不同版本。
  • 易于配置、扩展和自定义构建过程
  • 良好的IDE集成

Gradle的Android插件结合Android Studio成为了目前最为流行的Android构建系统。

2. Android Studio的模块类型和项目视图

Android Studio中的每个项目包含一个或多个含有源代码文件和资源文件的模块,这些模块可以独立构建、测试或调试,一个Android Studio的模块类型可以有以下几种:

Android应用程序模块
Android应用程序模块可能依赖于库模块,尽管许多Android应用程序只包含一个应用程序模块,构建系统会将其生成一个APK。

Android 库模块
Android库模块包含可重用的特定于Android的代码和资源,构建系统会将其生成一个AAR。

App 引擎模块
包含应用程序引擎集成的代码和资源。

Java 库模块
包含可重用的代码,构建系统会将其生成一个JAR包。

Android Studio3.3.2 中的Android项目视图如下所示。


Vep71s.png

所有构建文件在 Gradle Scripts 层级下显示,大概介绍下这些文件的用处。

  • 项目build.gradle:配置项目的整体属性,比如指定使用的代码仓库、依赖的Gradle插件版本等等。
  • 模块build.gradle:配置当前Module的编译参数。
  • gradle-wrapper.properites:配置Gradle Wrapper,可以查看Gradle核心思想(四)看似无用,实则重要的Gradle Wrapper这篇文章。
  • gradle.properties:配置Gradle的编译参数。具体配置见Gradle官方文档
  • settings.gradle:配置Gradle的多项目管理。
  • local.properties:一般用来存放该Android项目的私有属性配置,比如Android项目的SDK路径。

这篇文章主要介绍项目build.gradle和模块build.gradle。

3.项目build.gradle

我们新建一个Android项目,它的项目build.gradle的内容如下:

buildscript {
    repositories {
        google()
        jcenter()   
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2' //1
    }
}

allprojects {
    repositories {
        google()
        jcenter()  
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

注释1处配置依赖的Gradle插件版本,Gradle插件属于第三方插件,因此这里在buildscrip块中配置谷歌的Maven库和JCenter库,这样Gradle系统才能找到对应的Gradle插件。
如果使用google()not found: 'google()'错误,可以用如下代码替代:

maven { url 'https://maven.google.com' }

如果你还不理解Gradle插件,可以查看Gradle核心思想(五)通俗易懂的Gradle插件讲解这篇文章。

4.模块build.gradle

新建一个Android项目,它的模块build.gradle的内容如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    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'
}

4.1 Gradle的Android插件类型

apply引入的插件id为com.android.application,说明当前模块是一个应用程序模块,Gradle的Android插件有多个类型分别为:

  • 应用程序插件,插件id为com.android.application,会生成一个APK。
  • 库插件,插件id为com.android.library,会生成一个AAR,提供给其他应用程序模块用。
  • 测试插件,插件id为com.android.test,用于测试其他的模块。
  • feature插件,插件id为com.android.feature,创建Android Instant App时需要用到的插件。
  • Instant App插件,插件id为com.android.instantapp,是Android Instant App的入口。

4.2 Android块

Android块用于描述该Module构建过程中所用到的所有参数。

  • compileSdkVersion:配置编译该模块的SDK版本
  • buildToolsVersion:Android构建工具的版本
4.2.1 defaultConfig块

Android块中的defaultConfig块用于默认配置,常用的配置如下所示。

属性 描述
applicationId 指定App的包名
minSdkVersion App最低支持的SDK版本
targetSdkVersion 基于哪个SDK版本开发
versionCode App内部的版本号,用于控制App升级
versionName App版本名称,也就是发布的版本号
testApplicationId 配置测试App的包名
testInstrumentationRunner 配置单元测试使用的Runner,默认为android.test.InstrumentationTestRunner
proguardFile ProGuard混淆所使用的ProGuard配置文件
proguardFiles 同时配置多个ProGuard配置文件
signingConfig 配置默认的签名信息
4.2.2 buildTypes块

buildTypes块用于配置构建不同类型的APK。
当我们新建一个项目时,在Android块已经默认配置了 buildTypes块:

 buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

在AS的Terminal中执行gradlew.bat build命令,会在该模块的build/outputs/apk目录中生成release和debug的APK,虽然只配置了release ,但release和debug是默认配置,即使我们不配置也会生成。也可以修改默认的release和debug,甚至可以自定义构建类型,比如:

 buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug {
            debuggable true
        }
        privitedebug{
            applicationIdSuffix ""
        }
    }

这时会在build/outputs/apk目录中生成release、debug、privitedebug的APK。
buildTypes块还可以配置很多属性,常用的配置如下所示。

属性 描述
applicationIdSuffix 配置applicationId的后缀
debuggable 表示是否支持断点调试
jniDebuggable 表示是否可以调试NDK代码
buildConfigField 配置不同的开发环境,比如测试环境和正式环境
shrinkResources 是否自动清理未使用的资源,默认值为false
zipAlignEnabled 是否开启开启zipalign优化,提高apk运行效率
proguardFile ProGuard混淆所使用的ProGuard配置文件
proguardFiles 同事配置多个ProGuard配置文件
signingConfig 配置默认的签名信息
multiDexEnabled 是否启用自动拆分多个Dex的功能
4.2.3 signingConfigs块

用于配置签名设置,一般用来配置release模式。

属性 描述
storeFile 签名证书文件
storePassword 签名证书文件的密码
storeType 签名证书的类型
keyAlias 签名证书中密钥别名
keyPassword 签名证书中密钥的密码
signingConfigs {
        release {
            storeFile file('C:/Users/liuwangshu/.android/release.keystore')
            storePassword 'android'
            keyAlias 'androidreleasekey'
            keyPassword 'android'
           
        }
4.2.4 其他配置块

android块中除了前面讲的defaultConfig块、buildTypes块、signingConfigs块还有其他的配置块,这里列举一些。

描述
sourceSets 配置目录指向
productFlavors 多个渠道配置
lintOptions Lint配置
dexOptions DEX工具配置
adbOptions adb配置
packagingOptions 打包时的相关配置

更多的配置块请参考官方文档

4.2.4 全局配置

如果有多个module的配置是一样的,可以将这些配置提取出来,也就是使用全局配置。全局配置有多种方式,这里介绍其中的两种。
1. 使用ext块配置
在项目build.gradle中使用ext块,如下所示。

ext{
    compileSdkVersion =28
    buildToolsVersion ="28.0.3"
    minSdkVersion =15
    targetSdkVersion =28
}

在某个module的build.gradle中使用配置:

apply plugin: 'com.android.application'
android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    defaultConfig {
        applicationId "com.example.liuwangshu.hookinstrumentation"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
  ...
}
...

2. 使用config.gradle配置
首先在根目录下创建config.gradle文件来进行配置。
config.gradle

ext{
    android=[
            applicationId:"com.example.liuwangshu.hookinstrumentation",
            compileSdkVersion :28,
            buildToolsVersion :"28.0.3",
            minSdkVersion : 15,
            targetSdkVersion : 28,
    ]

    dependencies =[
            "appcompat-v7" : "com.android.support:appcompat-v7:28.0.0",
            "constraint"  : "com.android.support.constraint:constraint-layout:1.1.3",
    ]
}

接着在项目build.gradle中添加apply from: "config.gradle",这样项目的所有module都能用config.gradle中定义的参数。
最后在module的build.gradle中使用配置:

apply plugin: 'com.android.application'
android {
    compileSdkVersion rootProject.ext.android.compileSdkVersion
    buildToolsVersion rootProject.ext.android.buildToolsVersion
    defaultConfig {
        applicationId rootProject.ext.android.applicationId
        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
   ...
dependencies {
    implementation rootProject.ext.dependencies["constraint"]
    implementation rootProject.ext.dependencies["appcompat-v7"]
    ...
}

4.2 dependencies 块

dependencies 块用于配置该module构建过程中所依赖的所有库。Gradle插件3.4版本新增了 api 和 implementation 来代替 compile 配置依赖,其中 api 和此前的 compile是一样的。dependencies和api主要以下的区别:

  • implementation可以让module在编译时隐藏自己使用的依赖,但是在运行时这个依赖对所有模块是可见的。而api与compile一样,无法隐藏自己使用的依赖。
  • 如果使用api,一个module发生变化,这条依赖链上所有的module都需要重新编译,而使用implemention,只有直接依赖这个module需要重新编译。

感谢
https://jeroenmols.com/blog/2017/06/14/androidstudio3/
http://google.github.io/android-gradle-dsl/current/
http://www.androiddocs.com/tools/building/plugin-for-gradle.html
https://www.jianshu.com/p/8962d6ba936e
https://www.jianshu.com/p/b6744e1e4f7c
《Android群英传 神兵利器》

更多的内容请关注我的独立博客的知识体系:
http://liuwangshu.cn/system/


<div align=center>这里不仅分享大前端、Android、Java等技术,还有程序员成长类文章。</div>
<div align=center><img src="https://user-gold-cdn.xitu.io/2019/10/29/16e14c62122499d7?w=234&h=231&f=jpeg&s=34771" width="260"/></div>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容