[转载]深入理解 Gradle 编译一 Android 基础篇

内容来源

虽然内容为转载,但是自己也是经过详细学习和为文章重构的,^ ^

导读

 Gradle基于Groovy的特定领域语言(DSL)编写的一种自动化建构工具,Groovy作为一种高级语言由Java代码实现,本文将对Gradle一些常见问题进行一一介绍:
  1. 理解 Gradle 与 android app 之间的关系,以及 Gradle 需要构建的 build 文件。
  2. 在 Android Studio 中执行 Gradl e命令。
  3. 在 Android app 添加 java 库文件。
  4. 将 eclipse 工程导入 Eclipse ADT 工程
  5. 如何为一个 APK 文件进行数字签名

1. Android Gradle基础

 android 应用程序使用开源工具 Gradle 构建。Gradle 一种艺术 API,非常容易的支持定制,并且在 java 世界有着广泛的应用。`Android 为了实现编译、打包等,开发者开发了 Android插件为 Gradle 添加了一系列的新特征`,特别是在构建 Android app 上的应用,包括:构建类型、多样化、签名配置、库文件工程等等功能。
1.1 Android Gradle 构建文件

在我们使用 Android Studio工具开发 Android 应用的时候,当创建一个新的 Android 工程,默认的 Gradle 构建文件包括了setting.gradle,build.gradleapp/build.gradle。具体位置如图所示。

gradle 文件位置

setting.gradle

include ':app'

build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0+'
    }
}

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

其实原始的 Gradle 默认情况下并不包含 Android 功能。Google 为 Gradle 提供了Android 插件,允许用户很容易的配置 android 工程编译脚本。编译脚本 (buildscript) 在编译工程的根目录,构建文件 (build.gradle) 用来告知 Gradle 去哪里下载对应的插件。

从上面列出的代码中我们可以看到插件的默认下载是从 jcenter中,意味着 jcenter 就是当前的目标库。* 虽然 jcenter 仓库是当前默认的,但是其它的仓库也是支持的*,尤其是 mavenCenteral() 作为 maven 的远端默认仓库。JCenter 仓库的所有内容通过一个 CDN 经由 HTTPS 连接传输,速度也是很快的。

上面代码中的 allprojects 部分表示当前的根目录工程和所属的子工程默认情况下都使用 jcenter() 远端仓库用来支持java库的依赖。

Gradle 允许用户定义很多任务(tasks),并插入到有向无环图(directed acyclic graph,DAG)中,Gradle 通过 DAG 来解析任务之间的依赖关系。在上面代码中一个 clean 任务已经添加到根目录的构建文件中。其中的 type: Delete 表示依赖 Gradle 中定制已有的 Delete任务。在这种情况下,该任务会移除在工程根目录下的构建目录(也就是 build 目录)。

app 作为项目工程的 module (模块),内部需要包含 build.gradle 来支持 module 编译,接下来来看一下 app 目录下的 build.gradle。

app/build.gradle

apply plugin: 'com.android.application'
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.kousenit.myandroidapp"
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

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

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
}

这部分的代码功能并非由 Gradle 工具提供,是由 Android 插件构建系统提供,通过加入 android 标签,允许 android 块使用 DSL (Domin Specific Language) 编写配置。

dependencies 部分包含了三行。

  • 第一行使用fileTree做依赖,表示所有在libs目录下的以.jar为后缀名的文件添加到编译路径中。
  • 第二行告诉 Gradle 去下载版本为4.12的 JUnit 并为其添加命名 testCompile 。依赖着 JUni t类将在 src/androidTest/java
    路径下生效,用来增加测试单元(本文没有介绍测试)。
  • 第三行告诉 Gradle 添加 appcompat-v7,版本为 23.3.0,从 JCenter 支持库中获取。
1.2 默认配置

app/build.gradle

apply plugin: 'com.android.application'
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.kousenit.myandroidapp"
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

在 build.gradle 文件的顶部添加 Android 应用程序插件。Module (模块) 编译文件通过 apply plugin: 'com.android.application',加载应用程序插件,从而使 Gradle DSL 支持 android 标签。

android DSL 使用模块方式嵌入。必须指出编译目标版本(compileSdkVersion)和编译工具版本(buildToolsVersion)。两个值尽量跟进较近的版本,而非老版本,因为新版本会修复老版本工具含的一些bug 。

属性 解释
applicationId 应用的包名,该值必须唯一
minSdkVersion 应用支持的最小Android SDk版本
targetSdkVersion 应用目标版本,Android studio会根据当前版本提示相应的警告信息
versionCode 用一个整数表示当前app的版本,用以升级使用
versionName 用一个字符表示当前app版本名称,用以升级使用

转到 Gradle 之后,minSdkVersion 和 buildToolsVersio n属性被指定,这两个属性和 Android Manifest 中的 <uses-sdk> 标签属性内容一致。Android Manifest 中的 <uses-sdk> 标签已经被取消,如若值仍然存在在 Manifest 中,值将被 Gradle 中的值覆盖。

1.3 使用命令行执行Gradle脚本

从命令行需要用户提供 Gradle wrapper 或者安装 Gradle 并直接运行。

gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

其中 distributionUrl属性表示 wrapper 包将要下载和安装gradle-2.14.1
版本。在第一次执行结束之后,Gradle 目标将被缓存在 zipStorePath 文件夹,在 zipStoreBase 目录之下,以后每次构建将直接使用缓存的版本构建任务。

命令非常简单:

./gradlew build
最后输出的apk在app/build/outputs/apk目录下。我们也可以执行多任务通过空格:

** ./gradlew lint assembleDebug**
其中查看依赖树通过:

** ./gradlew anDep**

** 取消编译任务: ./gradlew pro**

如果不想使用编译build.gradle文件,使用-b切换编译脚本文件:

./gradlew -b app.gradle

1.4 在android Studio上执行编译脚本

如何在 Android Studio 环境下,执行编译任务?当我们创建 Android 工程后,Android Studio 会为多个工程脚本生成 Gradle 构建文件。IDE提供了Gradle任务列表的可视化视图,如下图所示:


Gradle提供了很多分类,像 android, build, install 和 other。执行某一个任务的时候只需要双击具体的名称,在 Gradle 窗口中。每次运行一个特殊的 task,运行配置就会被创建并存储在 Run Configurations 菜单下,所以再次运行的时候可以在这里选择。



Android studio 提供了 Gradle Console 输出相应的编译信息

1.5 为项目工程增加依赖库

默认情况下,Android 应用包含了两个 gradle 文件:一个在根目录下,一个在应用目录下。在应用目录下的 gradle 脚本需要增加依赖:
app/build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.3.0'
}

每一个依赖关系表示了一个配置。
Android 工程的依赖包含了编译、运行、测试编译、测试运行。完整的依赖包含三个部分:group,name, 和 version 信息。插件可以增加额外的配置信息,也能够定义自己的信息。完整的信息如下:


testCompile group: 'junit', name: 'junit', version: '4.12'

简写为:
testCompile 'junit:junit:4.12'

版本简写:
testCompile 'junit:junit:4.+'

如果你想配置相应的文件,可通过 filesfileTree增加依赖:

dependencies {
    compile files('libs/a.jar', 'libs/b.jar')
    compile fileTree(dir: 'libs', include: '*.jar')
}

传递依赖:

./gradlew androidDependencies
Gradle默认情况下是开始网络检查依赖库的,如果有特殊需求需要关闭,采用transitive标志关闭网络请求:

dependencies {
    runtime group: 'com.squareup.retrofit2', name: 'retrofit', version: '2.0.1', 
    transitive: false
}

将transitive标志改成false会阻止依赖的下载。所以如果需要的话必须加载自己的本地。如果希望模块是jar文件,写法如下:

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.4[@jar](https://my.oschina.net/u/1767170)'
    compile group: 'org.codehaus.groovy', name: 'groovy-all',version: '2.4.4', ext: 'jar'
}
1.6 为 android studio 增加依赖库

有经验的开发者可以很轻松的编辑 build.gradle 文件,而不需要借助 IDE 的帮助。但是 IDE 也给出了相应的编辑视图。

打开File->Project Structure,选择相应的 module s即可对 build.gradle 进行编辑。如下图所示:


  • 选择 Porperties 选项卡,可以查看 Compile SDK Version 和 Build Tools Version等信息。
  • 选择 Dependencies 选项卡,可以查看依赖的库、工程等信息。


其中Dependencies选项卡中的Scope行允许用户配置依赖库是提供到apk中,还是只是编译的时候依赖:

  • Compile
  • Provided
  • APK
  • Test compile
  • Debug compile
  • Release compile
1.7 配置仓库

在 Gradle 的 dependencies 是怎么样精准的找到相应的依赖的呢?通过在 repositories 配置的,所有的 dependencies 都会去找到相应的依赖,才可以正常编译。默认仓库为 JCenter。注意当前使用 HTTPS 连接。

repositories {
    mavenLocal()
    mavenCentral()
}

一些Maven库也可以通过URL添加,如下例添加一个maven库:

repositories {
    maven {
        url 'http://repo.spring.io/milestone'
    }
}

** 密码保护仓库 (需要进一步了解)**可以使用 credentials 模块来表示,通过用户名和密码的校验来获取依赖仓库,代码如下所示:

repositories {
    maven {
    credentials {
        username 'username'
        password 'password'
    }
    url 'http://repo.mycompany.com/maven2'
    }
}```
也可以将用户名和密码值移到 gradle.properties 文件中。Ivy 和 local 仓库语法类似,参考下例:

repositories {
ivy {
url 'http://my.ivy.repo'
}
}

当使用本地文件,可以通过flatDir语法来创建仓库,。如下例所示:

repositories {
flatDir {
dirs 'libs'
}
}```
使用 flatDir 是使用 files 或是 fileTree 方案的一种替代,fileTree 需要指定路径,就不再需要指定 flatDir 本地文件,但是 aar 文件依赖的时候需要指定本地库,使用 latDir 标签。当我们为应用程序构建添加很多仓库。Gradle 轮询每一个仓库,直到解析完毕所有的依赖,找到所有依赖,否则会报出错误 。

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

推荐阅读更多精彩内容