Android插件

Android插件

前面我们说到Gradle插件其实并没有提供真正的构建功能, 我们编译构建的Task很多都是由插件来提供的,如果对这点还不是很了解可以先看下Gradle脚本学习

Java插件

在某种意义上,android插件算是在java插件的基础上扩展而来的,而java插件也是Gradle官方支持的插件之一,为了让大家能够更好的理解Android插件中各个Task的执行和依赖关系,我们现对Java插件做一个介绍,英语好的同学可以直接去阅读Gradle官方The Java Plugin
Java插件的使用很简单,毕竟是官方支持的

apply plugin: 'java'

这样就可以了,对于java插件我们主要理解一张Tasks图表


javaPluginTasks.png

这里包含了java插件中的绝大部分Tasks,图标中的Task描述如下

名称 依赖 TaskType 描述
compileJava 所有处理编译过程的任务 JavaCompile 使用javac编译java源码
processResources - Copy 把资源文件复制到相应目录
classes complileJava和processResources Task 生成.class文件和资源文件目录
compileTestJava compile,加上编译测试文件的所有Task JavaCompile 使用javac编译java测试代码
processTestResources - Copy 把测试资源文件复制到相应目录
testClasses compileTestJava和processTestResources Task 申城测试的.class文件和资源文件目录
jar compile Jar 生产jar文件
javadoc compile Javadoc 使用javadoc生产Api文档
test compile Test 使用JUnit或TestNG运行单元测试
uploadArchives 生成所有archives需要的artifacts文件的Task,包括jar Upload 使用archives配置上传artifacts包括jar文件
assemble 项目中的所有archive任务,包括jar Task 生成项目所有的archive文件
check 项目中的所有验证任务,包括test Task 执行所有项目中的验证任务
build assemble和check Task 执行完整的项目构建
clean - Delete 删除项目构建过程生成的文件目录
clean TaskName - Delete 删除指定任务创建的文件。 cleanJar将删除由jar任务创建的JAR文件,cleanTest将删除测试任务创建的文件

我们平时使用当然不可能一步步去编译,往往只会使用几个相对简单的命令,比如check、assemable之类的,但是如果我们对整个build的流程不了解,我们就很难在构建过程中对某一个具体的行为进行优化,这里先讲解java插件,是因为java的构建过程相对简明,Android工程的构建过程就相对复杂很多,但是本质上都差不多,建议大家还是可以先学习下

Android插件

Android插件是由google提供,用于配置、编译、打包android工程,它提供了一些新的DSL和task供我们配置,执行android工程的编译打包过程,关于android插件的使用个人建议可以看下Google提供的GradlePluginUserGuideAndroidPluginDSL,这里我就算是抛砖引玉了

基本配置

android下最基本的配置很简单,完成最基本的配置之后Gradle就能够对我们的project进行构建,同时还有一些的零碎的配置,我也一并并在这里进行说明最最简单的,我们只需要配置compileSdkVersion和buildtoolsVersion

apply plugin: 'com.android.application' 
android { 
    compileSdkVersion 25 
    buildToolsVersion "25.0.0" 
}

这样就可以完成构建,当然我们还需要配置一些Apk的基本信息,这些信息主要通过defaultConfig{}来进行配置,主要的信息如下

  • minSdkVersion
  • targetSdkVersion
  • versionCode
  • versionName
  • applicationId
  • testApplicationId (used by the test APK)
  • testInstrumentationRunner

前四条都是一些基本的版本配置信息其中值得一提的是applicationId 这条属性,形式上和packageName是一致的,当我们使用AndroidStudio创建工程是,applicationId默认是和packageName一样,但是这两者是有本质区别的,packageName是可以改变的,但是applicationId一旦应用发布就不能修改了,applicationId是APK的标识,同时不同渠道版本的applicationId最好也进行不同的配置,这个稍后进行详细说明
关于test的配置信息,也会在后面的章节详细说明

sourceSets

资源目录Android插件的默认资源目录如下

src/ 
├──main/ 
│     ├── java/ 
│     ├── resources/ 
│     ├── res/
│     ├── assets/ 
│     ├── aidl/ 
│     ├── rs/ 
│     ├── jni/ 
│     ├── jniLibs/ 
│     └── AndroidManifest.xml 
├── test/ 
└── androidTest/

如果需要更改目录需要手动修改,例如对于一般的eclipse工程我们可以使用下面的配置

android { 
    sourceSets { 
        main { 
            manifest.srcFile 'AndroidManifest.xml' 
            java.srcDirs = ['src'] 
            resources.srcDirs = ['src'] 
            aidl.srcDirs = ['src'] 
            renderscript.srcDirs = ['src'] 
            res.srcDirs = ['res'] 
            assets.srcDirs = ['assets'] 
        }  
        androidTest.setRoot('tests') 
    } 
}

这样就无需手动更改文件目录,也可以直接编译

Dependencies Configration

前面我们说到dependencies本质上就是一个配置信息,Android插件提供的dependencies主要有:

  • compile: main application
  • androidTestCompile: test application
  • debugCompile: debug Build Type
  • releaseCompile: release Build Type
  • testComplie:上面四种是google官方文档上写的,事实上testComplie这种纯java的test配置也是支持的

根据版本变种,android插件也会生成不同的dependencies,就像android自带的两种buildtype就生成了上面两种dependencies

Android Tasks

前面在gradle我们说到,在gradle中实际的执行是通过Task来进行的,Android插件能够对我们的Project进行构建,必然也提供了相应的Task才能完成构建,我们主要要用到的主要有下面几个

  • assemble生成输出,会执行构建过程
  • check运行所有检查任务
  • connectedCheck运行检查连接的设备或模拟器,所有连接的设备将并行运行。
  • deviceCheck使用API​​运行检查以连接到远程设备,这在CI服务器上使用。
  • build这个任务会运行assemble和check。
  • clean此任务清除项目的输出。

感觉和java插件大体相似,只是多了两个类似设备检查之类的task,但是事实上,android工程的构建过程还是比较复杂的,所以android插件并没有给出构建过程中具体的tasks,以及task间的依赖关系,更没有java插件中提供的task依赖表。

那么我们要怎么才能弄清android构建的具体过程呢,这里我为大家介绍一个插件Inspector,具体使用方法参考GitHub:https://github.com/jakeouellette/inspector,我就不多做介绍,这个插件可以生成我们所运行的task的依赖关系图,方便大家理解学习。

注意:Inspector不支持windows!不支持windows!不支持windows!

版本变种的配置

BuildType配置

版本变种中有两个内容,BuildType和ProductFlavor,首先是关于BuildType,Android插件默认提供debug和release两种BuildType,当然我们也可以自己添加新的BuildType,Android下对于每一种BuildType都可以有各自的配置信息,同时可以根据配置信息生成独特apk,首先对于不同的BuildType,我们会有不同的dependencies配置compile类型,就像上面 dubugCompile一样,类似下面的代码

android { 
    buildTypes { 
        jnidebug { 
        } 
    } 
}

就会生成一个jnidebugCompile,前面我们说过aseemble这个task可以生产所有的输出,这里我们有三个BuildType,即assemble会生成3个不同Apk,如果我们只需要生成debug的Apk,这里和compile一样,Android插件也会生成一个assembleDubug的task,运行assembleDubug则不会生成其他版本的Apk
BuildType的配置就在buildTypes{}的闭包中

android {
    buildTypes {
        debug {
            applicationIdSuffix ".debug"
        }
        jnidebug {
            initWith(buildTypes.debug)           
            applicationIdSuffix ".jnidebug"
            jniDebuggable true
        }
    }
}

其实我觉得这些东西反而没有什么好讲的,配置基本上就是一个表,列出所有可配置的东西,这里我姑且还是把一些我感觉可用的配置和方法都列出来,大家也可以参考官方文档

名称|类型|说明
---|--|--|--
applicationIdSuffix|String|为 applicationId添加后缀,applicationId是app唯一标识,每次调用都是在最开始的applicationId上添加
debuggable|Boolean|调试开关
consumerProguardFiles|List<File>|生成的aar文件中的混淆规则,只针对Library工程
jniDebuggable|Boolean|jniDebug开关
minifyEnabled|Boolean|混淆开关
signingConfig|SigningConfig|签名配置
proguardFiles|List<File>|生成apk时使用的混淆配置文件
shrinkResources|Boolean|移除没有用到的资源文件,默认为false
embedMicroApp|Boolean|Android Wear app是否需要嵌入此build type
manifestPlaceholders|Map<String, Object>|配置manifest属性,合并时使用这里的属性
multiDexEnabled|Boolean|Multi-Dex开关
multiDexKeepFile|File|main dex的配置文件,text文件,每行指定一个class文件,格式为com/example/MyClass.class
multiDexKeepProguard|File|main dex的混淆规则,会和构建系统的混淆规则合并
zipAlignEnabled|Boolean|压缩对齐开关
[buildConfigField](http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:buildConfigField(java.lang.String, java.lang.String, java.lang.String))(String, String, String)|Method|为生成的BuildConfig添加键值对
initWith(BuildType)|Method|复制所有属性

SigningConfig

Android 要求所有 APK 必须先使用证书进行数字签署,然后才能安装。Android插件已经帮我们配置了两种BuildType:debug和release,其中debug默认使用Android自动生成的dubug Signing,而release默认是没有配置Signing的,我们可以直接在代码中进行Signing的配置

android {
    signingConfigs {
        release{
            storeFile file("other.keystore")
            storePassword "android"
            keyAlias "androiddebugkey"
            keyPassword "android"
        }
    }
    buildTypes {
        release{
            signingConfig signingConfigs.release
        }
    }    
}

这里我们我们通过signingConfigs{}配置了一个release的signing,然后在配置buildTypes 的时候把它配置到,release的配置闭包中, 这里可以简单的把signingConfigs理解为一个配置文件,在上面我们直接keystore的pwd写在了代码中, 一般是不建议这么,我们通常使用一个专门的配置文件来存储signingConfigs,需要的时候从文件中读取,或者从控制台输入。

BuildConfig

在编译时期,Android插件会生成一个BuildConfig的类,包含部分Gralde配置中的常量默认BuildConfig有下列信息:

  • boolean DEBUG 是否可以dubug
  • int VERSION_CODE
  • String VERSION_NAME
  • String APPLICATION_ID
  • String BUILD_TYPE – name of the build type, e.g. "release"
  • String FLAVOR – name of the flavor, e.g. "paidapp"

同时我们也可以通过buildConfigField(String, String, String)把我们需要的配置信息加入到BuildConfig中

ProductFlavor配置

ProductFlavor的配置和BuildType基本类似,同时也会生成相应的Task和Compile,主要区别就是BuildType的分类是针对开发者的,如debug、release,而ProductFlavor的分类是针对用户的,如free、pay,所以可配置的内容是不同的,ProductFlavor的配置信息主要如下:

名称|类型|说明
---|--|--|--
applicationId|String|-
applicationIdSuffix|String|为 applicationId添加后缀,applicationId是app唯一标识,每次调用都是在最开始的applicationId上添加
consumerProguardFiles|List<File>|生成的aar文件中的混淆规则,只针对Library工程
dimension|String|此flavor的dimensioin类型
externalNativeBuild|ExternalNativeBuildOptions|封装了native相关构建的信息
jackOptions|JackOptions|jack配置
signingConfig|SigningConfig|签名配置
proguardFiles|List<File>|生成apk时使用的混淆配置文件
manifestPlaceholders|Map<String, Object>|配置manifest属性,合并时使用这里的属性
multiDexEnabled|Boolean|Multi-Dex开关
multiDexKeepFile|File|main dex的配置文件,text文件,每行指定一个class文件,格式为com/example/MyClass.class
multiDexKeepProguard|File|main dex的混淆规则,会和构建系统的混淆规则合并
[buildConfigField](http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:buildConfigField(java.lang.String, java.lang.String, java.lang.String))(String, String, String)|Method|为生成的BuildConfig添加键值对
maxSdkVersion(int or String)|Method|设置flavor最高sdk版本
minSdkVersion(int or String)|Method|设置flavor最低sdk版本

Build Variant

我们知道一种BuildType会生产一种Apk,ProductFlavor也是一样的,那个一个工程可以产出的不同种类的apk将是这两者的合并,比如一个有两个Flavor的工程,加上默认的BuildType,则会生成下面几个版本:

  • Flavor1 - debug
  • Flavor1 - release
  • Flavor2 - debug
  • Flavor2 - release

Build Type + Product Flavor = Build Variant

Sourcesets and Dependencies

不同的BuildVariant可以有不同的资源和依赖,他们同时共享主目录下的资源,举个例子flavor1Debug这样一个Variant,它的资源可能来自如下目录

  • android.sourceSets.main
    位于 src/main/
  • android.sourceSets.flavor1
    位于 src/flavor1/
  • android.sourceSets.debug
    位于 src/debug/
  • android.sourceSets.flavor1Debug
    位于 src/flavor1Debug/

如果出现同名的文件那么他们的优先级顺序是flavor1Debug>debug>flavor1>main,一层会覆盖一层。对于Dependencies,这个规则也是一样的。

小结

Android插件的内容并不算多,但是想要用好Gradle,我们除了要了解这些东西之外,还需要了解Gradle和Groovy提供的API以及一些其他的插件才能更好的使用它。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,449评论 25 707
  • 最近几年移动开发业界兴起了「 插件化技术 」的旋风,各个大厂都推出了自己的插件化框架,各种开源框架都评价自身功能优...
    斜杠时光阅读 3,940评论 1 36
  • 1.介绍 如果你正在查阅build.gradle文件的所有可选项,请点击这里进行查阅:DSL参考 1.1新构建系统...
    Chuckiefan阅读 12,115评论 8 72
  • 转载注明出处:http://www.jianshu.com/p/5255b100930e 0. 前言 完全由个人翻...
    王三的猫阿德阅读 2,501评论 0 4
  • 第一看电影,感觉作为一名中国人,很自豪。 几乎,连着二刷,四个小时,从电影院出来,膝盖疼,难道被空调吹的? 难得国...
    乘格帆阅读 559评论 5 3