Gradle for Android简要指南

前言 Android官网构建系统介绍https://developer.android.com/studio/build/index.html

Gradle 是 Android 现在主流的编译工具,虽然在Gradle 出现之前和之后都有对应更快的编译工具出现,但是 Gradle 的优势就在于它是亲儿子,Gradle 编译比较慢,这和它的编译过程有关,但是最近伴随着 Android Studio2.0的发布(目前官网最新gradle 为2.2.0), Gradle 也进行了一次非常大的升级,叫Instant Run.它的编译速度网上有人用逆天两个字来形容。(虽然目前有 Bug 我们要相信,他会好的) 对于一些比较复杂的,特别是多人团队合作的项目我们会需要一些个性化的配置来提高我们的开发效率。一些高级功能需要我们手动的去配置gradle脚本。 按官网流程一一介绍,有疏漏的请留言,我们一起学习 首先来张大图

Paste_Image.png

对于一个典型的Android应用程序模块构建过程,遵循以下一般步骤:

1. 编译器转换你的源代码转换成DEX(Dalvik的可执行文件)的文件,其中包括Android设备上运行的字节码,和其他一切编译资源。

2. 该APK包装结合了DEX文件,资源编译成一个单一的APK。之前可以安装你的应用程序并部署到Android设备,但是,APK必须签名。

3. 该APK打包签署使用Debug或发布密钥库您的APK: a. 如果您正在构建您的应用程序,这是一个调试版本,应用程序你打算仅用于测试和分析后,打包签署您的应用程序与调试密钥库。Android Studio中自动配置与调试密钥库的新项目。 b. 如果您正在构建您的应用程序,你要在外部释放的发行版中,打包签署您的应用程序一起发布密钥库。要创建一个发布密钥库,了解Android Studio中签署您的应用程序。

4. 产生最终的APK之前,打包使用zipalign工具来优化您的应用程序在设备上运行时,使用较少的内存。

在构建过程的最后,您有一张调试APK或释放您的应用程序,你可以用它来部署,测试或释放到外部用户的APK。

以上是官网对apk打包过程的一个简要概括,我们根据官网对gradle进行一个简单的介绍:

1. Build Types 定义了编译类型,针对每个类型我们可以有不同的编译配置,不同的编译配置对应的有不同的编译命令。默认的有debug、release 的类型。

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

   debug {
       applicationIdSuffix ".debug"
   }

2. Product Flavors 如果我们需要针对同一份源码编译不同的程序(包名也不同),比如 免费版和收费版。我们就需要Product flavors。 注意,Product flavorsBuild Type是不一样的,而且他们的属性也不一样。所有的 product flavor 版本和defaultConfig 共享所有属性! 像Build type 一样,product flavor 也可以有自己的source set 文件夹。除此之外,product flavor 和 build type 可以结合,他们的文件夹里面的文件优先级甚至高于 单独的built type 和product flavor 文件夹的优先级。如果你想对于 blue类型的release 版本有不同的图标,我们可以建立一个文件夹叫blueRelease ,注意,这个顺序不能错,一定是 flavor+buildType 的形式。

productFlavors {
     demo {
         applicationId "com.example.myapp.demo"
         versionName "1.0-demo"
     }
     full {
         applicationId "com.example.myapp.full"
         versionName "1.0-full"
     }
 }

3. Build Variants 在开发中我们可能会有这样的需求: -- 我们需要在debug 和 release 两种情况下配置不同的服务器地址; -- 当打市场渠道包的时候,我们可能需要打免费版、收费版,或者内部版、外部版的程序。 -- 渠道首发包通常需要要求在欢迎页添加渠道的logo。等等 -- 为了让市场版和debug版同时存在与一个手机,我们需要编译的时候自动给debug版本不一样的包名。 这些需求都需要在编译的时候动态根据当前的编译类型输出不同样式的apk文件。这时候就是我们的buildType大展身手的时候了。

4. Manifest Entries 您可以在构建变量的配置清单文件的一些属性的值。这些构建值清单文件覆盖现有值。如果您想为您的模块,其中每个APK文件有不同的应用程序名称,最小的SDK版本,或目标SDK版本多个APK这是非常有用的。

defaultConfig {/**
 * applicationId uniquely identifies the package for publishing.
 * However, your source code should still reference the package name
 * defined by the package attribute in the main/AndroidManifest.xml file.
 */applicationId 'com.example.myapp'// Defines the minimum API level required to run the app.minSdkVersion 14// Specifies the API level used to test the app.targetSdkVersion 23// Defines the version number of your app.versionCode 1// Defines a user-friendly version name for your app.versionName "1.0"}

5. Dependencies 构建系统管理从本地文件系统,并从远程仓库项目的依赖。这可以使您不必手动搜索,下载和你的依赖的二进制包拷贝到你的项目目录 。这里提供下marven仓库的搜索地址:http://search.maven.org/ 不用翻墙也可以的哦

android {...}
...
dependencies { // The 'compile' configuration tells Gradle to add the dependency to the
 // compilation classpath and include it in the final package.

 // Dependency on the "mylibrary" module from this project
 compile project(":mylibrary") // Remote binary dependency
 compile 'com.android.support:appcompat-v7:23.4.0'

 // Local binary dependency
 compile fileTree(dir: 'libs', include: ['*.jar'])
}

6. Signing 如果我们打包市场版的时候,我们需要输入我们的keystore数据。如果是debug 版本,系统默认会帮我们配置这些信息,秘钥在home/.android/debug.keystore。这些信息在gradle 中都配置在signingConfigs中。

android {
 signingConfigs {
     config {
         keyAlias keystoreProperties['keyAlias']
         keyPassword keystoreProperties['keyPassword']
         storeFile file(keystoreProperties['storeFile'])
         storePassword keystoreProperties['storePassword']
     }
 } ...}

7. ProGuard 构建系统使您可以指定每个构建变量不同ProGuard的规则文件。构建系统可以运行ProGuard的构建过程中缩小和模糊处理的类。说白了,就是在gradle中进行混淆配置

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

Note: Android Studio disables ProGuard when using Instant Run.

8. APK Splits 构建系统可以自动建立不同的APK,每个只包含代码,需要一个特定的屏幕密度或应用程序二进制接口(ABI)的资源。

android {
...
splits { // Configures screen density split settings
 density {   // Enables density APK splits
   enable true

   // Specifies a list of screen densities Gradle should not create APK splits for
   exclude "ldpi", "xxhdpi", "xxxhdpi"

   // Specifies a list of compatible screen size settings for the manifest
   compatibleScreens 'small', 'normal', 'large', 'xlarge'
 }
}
}

当启动一个新的项目,Android的Studio会自动创建一些这些文件对你来说,并填充它们基于合理的默认值。

Paste_Image.png

1. The Gradle Settings File

2. The Top-level Build File

3. The Module-level Build File

4. Gradle Properties Files 目录结构及gradle详细说明官网都说的很清晰 https://developer.android.com/studio/build/index.html#build-files, 掌握了以上的基本结构和基本写法,简单的Android工程构建基本上不会有什么问题了 有gradle语法不了解的童鞋可直接查看官网代码 https://docs.gradle.org/current/userguide/userguide.html 很庞大知识体系,接下来我们稍微了解一些与Android相关的gradle进阶应用

Gradle脚本不是像传统的xml文件那样,而是一种基于Groovy的动态DSL,而Groovy语言是一种基于jvm的动态语言。

Project和tasks 在grade中的两大重要的概念,分别是project和tasks。每一次构建都是有至少一个project来完成,所以Android studio中的project和Gradle中的project不是一个概念。每个project有至少一个tasks。每一个build.grade文件代表着一个project。tasks在build.gradle中定义。当初始化构建进程,gradle会基于build文件,集合所有的project和tasks,一个tasks包含了一系列动作,然后它们将会按照顺序执行,一个动作就是一段被执行的代码,很像Java中的方法。 构建的生命周期 一旦一个tasks被执行,那么它不会再次执行了,不包含依赖的Tasks总是优先执行,一次构建将会经历下列三个阶段:

Paste_Image.png

生命周期事件可以在指定的生命周期之前、之中或者之后发生,在执行阶段之后发生的生命周期事件就该是构建的完成了。假设你希望在构建失败时能够在开发阶段尽早得到反馈,给构建生命周期事件添加回调有两种方法:一是通过闭包,二是实现Gradle API的一个监听接口,Gradle并没有要求你监听生命周期事件,这完全决定于你,通过监听器实现的优势就是可以给你的类写单元测试,看看下面这幅图会有一点直观的印象:

Paste_Image.png

在配置阶段,Gradle决定在任务在执行阶段的执行顺序,依赖关系的内部结构是通过直接的无环图(DAG)来表示的,图中的每一个任务称为一个节点,每一个节点通过边来连接,你很有可能通过dependsOn或者隐式的依赖推导来创建依赖关系。记住DAG图从来不会有环,就是说一个已经执行的任务不会再次执行,下面这幅图将要的展示了这个过程:

项目结构 和eclipse对比来看,Android studio构建的结构有很大的不同:

 MyApp
   ├── build.gradle
   ├── settings.gradle
   └── app
       ├── build.gradle
       ├── build
       ├── libs
       └── src
           └── main
               ├── java
               │   └── com.package.myapp
               └── res
                   ├── drawable
                   ├── layout
                   └── etc.

gradle使用了一个叫做source set的概念,官方解释:一个source set就是一系列资源文件,其将会被编译和执行。对于Android项目,main就是一个source set,其包含了所有的资源代码。当你开始编写测试用例的时候,你一般会把代码放在一个单独的source set,叫做androidTest,这个文件夹只包含测试。(此处不做测试开发可以不用了解) 使用Gradle Wrappe防止新版本迭代所导致的问题 grade只是一个构建工具,而新版本总是在更迭,所以使用Gradle Wrapper将会是一个好的选择去避免由于gradle版本更新导致的问题。Gradle Wrapper提供了一个windows的batch文件和其他系统的shell文件,当你使用这些脚本的时候,当前gradle版本将会被下载,并且会被自动用在项目的构建,所以每个开发者在构建自己app的时候只需要使用Wrapper。所以开发者不需要为你的电脑安装任何gradle版本,在mac上你只需要运行gradlew,而在windows上你只需要运行gradlew.bat。 在目录指定gradle插件版本

dependencies { classpath 'com.android.tools.build:gradle:1.2.3' }

,在项目的gradle/wrapper目录下面有个gradle-wrapper.properties中有如下内容:

distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

修改URL也可以对gralde插件版本的控制。

关于gradle具体用法,我们后续再更新,gradle用法太杂,我们慢慢梳理 ?


Android历练记 是一个关于Android最新技术探讨,包含安全,架构,Android技术开发,ui绘制,源码解析等领域,如果你有兴趣,我们可以一起讨论学习, 关注微信公众号 Android历练记 或扫一扫二维码:

Android历练记

原文发布于微信公众号 - Android历练记(gh_db8538619cdd)

原文发表时间:2016-10-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大魏分享(微信公众号:david-share)

API管理对SOAP的集成&自定义开发者门户 | API Management学习第五篇

通常情况下,API管理对web API的集成,除了RESTful Web服务之外,还需要管理基于SOAP的Web服务。

1592
来自专栏杂烩

SSM项目搭建之MyBatis 原

    MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了goog...

762
来自专栏小狼的世界

使用PHP脚本来写Daemon程序

这又是一个有趣的概念,daemon在英语中是"精灵"的意思,就像我们经常在迪斯尼动画里见到的那些,有些会飞,有些不会,经常围着动画片的主人公转来转去,啰里啰唆地...

1422
来自专栏FreeBuf

看我如何使用TheFatRat接管你的Android手机

在这篇文章中,我们将教大家如何使用TheFatRat这款工具。这款工具可以帮大家构建后门程序,以及执行后渗透利用攻击等等。在主流Payload的帮助下,这款工具...

9872
来自专栏IT米粉

IntelliJ IDEA插件——冷门神器分享

IntelliJ IDEA就不必介绍了,至今还能保持IDE前三的神器,如今java程序员的首选,今天介绍几款冷门但绝对是神器的IDEA插件。 前言 IDEA自不...

5206
来自专栏zhisheng

HBase 集群监控

为什么需要监控? 为了保证系统的稳定性,可靠性,可运维性。 掌控集群的核心性能指标,了解集群的性能表现。 集群出现问题时及时报警,便于运维同学及时修复问题。 集...

6088
来自专栏开源项目

码云推荐 | J2EE 快速开发平台 renren-security-boot

renren-security-boot 是一款基于代码生成器的 J2EE 快速开发平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展;使用 Spring...

4358
来自专栏前沿技墅

再聊服务化基石:也有IO的事儿

1495
来自专栏解Bug之路

解Bug之路-Druid的Bug 原

笔者很热衷于解决Bug,同时比较擅长(网络/协议)部分,所以经常被唤去解决一些网络IO方面的Bug。现在就挑一个案例出来,写出分析思路,以飨读者,希望读者在以后...

1485
来自专栏MelonTeam专栏

[译]Android Instant Apps简介

导语 : Google最近发布了Instant Apps,可以帮助开发者进一步的增强Android的原生App体验。Instant Apps旨在通过在需要时只下...

3957

扫码关注云+社区

领取腾讯云代金券