Gradle的Android插件

Stella981
• 阅读 770

Android构建系统由一个_Gradle_的Android插件组成。 Gradle是一个高级的构建工具集,它可以管理依赖,并使你能够定义定制化的构建逻辑。Android Studio使用了一个Gradle包装器来完整地集成Gradle的Android插件。Gradle的Android插件也可以独立于Android Studio而运行。这意味着你可以用Android Studio构建你的Android apps,也可以从你机器的命令行或没有安装Android Studio的机器上构建你的Android apps(比如持续集成服务器)。

无论你是使用命令行,远程主机还是Android Studio来构建一个项目,构建的输出都相同。

构建配置(Build Configuration)

你的项目的构建配置(build configuration)在build.gradle文件里定义,它们都是使用Gradle语法和选项及Android插件的纯文本文件,它们配置了你的构建的如下几个方面:

_Build variants_。构建系统可以为相同的模块,根据不同的产品及构建配置产生多个APKs。当你想要构建你的应用程序的不同版本时这很有用,它使你不需要为每个版本创建一个不同的项目或模块。

_依赖_。构建系统管理项目依赖,并支持对本地文件系统及远程仓库的依赖。这使你可以不再不得不搜索,下载,复制你依赖的二进制包到你的项目。

_Manifest entries_。构建系统使你能够在build variant配置中指定manifest文件的某些元素的值。这些构建值会覆盖manifest文件里的已有值。如果你想要为你的模块产生多个APKs这很有用,其中每个apk文件具有一个不同的应用程序名称,最小SDK版本,或目标SDK版本。当有多个manifests出现时,manifest设定以buildType和productFlavor,/main manifest,和library manifests的优先级进行合并。

_签名_。构建系统使你能够在构建配置中指定签名设定,它还可以在构建过程中签名你的APKs。

_ProGuard_。构建系统使你能够为每个build variant指定一个不同的ProGuard规则文件。构建系统可以在构建过程中运行ProGuard来混淆你的类。

_测试_。对于大多数的模板,构建系统创建一个测试目录,androidTest并由你的项目的测试代码产生一个测试APK,因而你不需要创建一个单独测试项目。构建系统还能在构建过程中运行你的测试。

Gradle构建文件使用了领域特定语言(Domain Specific Language,DSL)通过_Groovy_语法来描述和控制构建逻辑。Groovy是一个动态语言,你可以用它定义定制的构建逻辑,及与Gradle的Android插件所提供的Android特有元素进行交互。

按照惯例构建(Build by Convention)

Android Studio构建系统对于项目的结构及其它构建选项的_预设行为_有一些假定。如果你的项目符合这些惯例,你的Gradle构建文件将非常简单。当这些惯例中的一些不适用于你的项目时,构建系统的灵活性使你能够配置构建过程的几乎每个方面。比如,如果你需要替换你的模块目录里的默认源码文件夹,你可以在模块的构建文件(build file)中配置一个新的目录结构。

项目和模块设定

Android Studio里的一个_project_,代表最顶层的Android开发结构。Android Studio工程包含工程文件和一个或多个应用程序模块。一个_模块_是你app的一个组件,你可以独立地对它进行构建,测试或调试。模块包含你的apps的源代码和资源。Android Studio工程可以包含多种模块:

_Android应用程序模块_包含应用程序(mobile,TV,Weat,Glass)代码,它可能依赖于库模块(library modules),尽管许多Android apps只由一个应用程序模块组成。构建系统会为应用程序模块产生APK包。

_Android库模块_包含可复用的Android特有代码和资源。构建系统会为库模块产生一个AAR(Android ARchive)包。

_App引擎模块_包含App引擎集成的代码和资源。

_Java库模块_包含可复用的代码。构建系统会为Java库模块产生一个JAR包。

Android Studio工程包含一个顶层的Gradle构建文件,它使你可以为工程里的所有应用程序模块添加共用的配置选项。每个应用程序模块又有它自己build.gradle文件,来进行那个模块特有的构建设定。

工程构建文件

默认情况下,工程级的Gradle文件使用_buildscript元素_来定义Gradle_仓库(repositories)_和_依赖(dependencies)_。这使得不同的工程可以使用不同的Gradle版本。支持的仓库包括JCenter,Maven Central,或Ivy。这个例子声明构建脚本使用JCenter仓库,及一个包含1.0.1版Gradle的Android插件的classpath dependency artifact。

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.1'

        // NOTE: Do not place your application dependencies here: they belong
        // in the individual module build.gradle files
    }
}

allprojects {
   repositories {
       jcenter()
   }
}

注意:Android Studio工程的SDK位置由_local.properties_文件里的sdk.dir设定设置,或通过ANDROID_HOME环境变量设置。

模块构建文件

应用程序模块Gradle构建文件使你能够配置模块构建设定,这包括覆盖src/main manifest设定,及设置定制的打包选项。

android settings

  • compileSdkVersion
  • buildToolsVersion

defaultConfig和productFlavors

  • manifest属性,比如applicationId,minSdkVersion,targetSdkVersion,和测试信息。

buildTypes

  • 构建属性,比如debuggable, ProGuard开关,debug签名,version name 后缀和testinformation。

dependencies

这个例子应用Android插件,使用默认的配置来覆盖多个manifest属性,创建两个build types:release和debug,并声明了一些依赖:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.mycompany.myapplication"
        minSdkVersion 13
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

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

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:20.0.0'
    compile project(path: ':app2, configuration: 'android-endpoints')
}

注意:你可以为属性值注入定制的构建逻辑,属性值由一个函数定义,而函数又会被属性调用,比如:

def computeVersionName() {
  ...
}

android {
    defaultConfig {
        versionName computeVersionName()
        ...
    }
}

依赖

Android Studio构建系统能够管理工程依赖,它支持模块依赖,本地二进制依赖,和远程二进制依赖。

模块依赖

一个应用程序模块可以在它的构建文件中包含一个它所依赖的其它模块的列表。当构建这个模块的时候,构建系统会汇集并包含这些需要的模块。

本地依赖

如果一个模块依赖于你本地文件系统中已有的二进制包,比如JAR文件,你可以为那个模块在构建文件中声明这种依赖。

远程依赖

当你的某些依赖可以在一个远程仓库中获得时,你就不需要下载它们并把它们复制到你的工程里了。Android Studio构建系统支持仓库的远程依赖,比如Maven,和依赖管理器,比如Ivy

许多流行的软件库和工具都可以在公共的Maven仓库中获得。对于这些依赖,你只需要指定它们的Maven坐标即可,Maven坐标可以唯一地标识一个远程仓库中的每一个元素。构建系统中使用的Maven坐标的格式为group:name:version。比如16.0.1版的Google Guava库的Maven坐标为com.google.guava:guava:16.0.1。

Maven Central Repository被广泛地用于分发多种库和工具。

Build Tasks

Android Studio构建系统定义了一个build tasks的分层集合:顶层的或祖先的tasks调用它依赖的tasks来处理它的集合构建输出。顶层的build tasks有:

assemble

  • 构建工程输出。

check

  • 执行检查和测试。

build

  • assemble和check都执行。

clean

  • 执行清理动作。

Android插件提供了connectedCheck和deviceCheck tasks来在connected,emulated,和remote devices时执行检查。可以通过点击右侧的Gradle标签查看Gradle tasks。

你可以在Android Studio或在命令行中查看所有可用tasks的列表并调用其中的任何一个,正如Building and Running from Android StudioBuild the project from the command line中所描述的那样。

Gradle包装器

Android Studio工程包含有_Gradle包装器_,它由如下几部分组成:

  • 一个JAR文件
  • 一个属性文件
  • 一个Windows平台的shell脚本
  • 一个Mac和Linux平台的shell脚本

注意:你应该把所有这些文件都提交到你的源码版本控制系统里。

使用Gradle包装器(而不是本地安装的Gradle)可以确保你能够总是运行_local.properties_文件中定义Gradle版本。要配置你的工程使用一个更新的Gradle版本,只需要修改属性文件并指定一个新的版本即可。

Android Studio从你工程里的Gradle包装器目录下读取属性文件,并在这个目录运行包装器,这样你就可以无障碍地同时工作于多个需要不同Gradle版本的工程上了。

注意:Android Studio不使用shell脚本,因而当你用IDE进行构建时,你对shell脚本做的任何修改都不会起作用。你应该转通过Gradle构建文件来定制你的构建逻辑。

你可以在开发机或其它没有安装Android Studio的机器的命令行中运行shell脚本来构建你的工程。

注意:当你创建一个工程时,请只使用来自于一个可靠来源的Gradle包装器脚本和JAR文件,比如Android Studio产生的那些。

Build Variants

在构建系统中,你的app的每个版本由一个_build variant_表示。Build variants是product flavors和build types的组合。Product flavors表示一个app的产品构建版本,比如免费版和付费版。Build types代表为每个app包产生的构建打包版本,比如debug和release。构建系统会为每个product flavors和build types的组合产生APKs。

默认情况下,Android Studio定义了默认的配置设定,在build.gradle文件中的defaultConfig,及两个build types (debug和release)。这将创建两个build variants,debug和release,构建系统将会为每个variant产生一个APK。

在默认的build types _debug_和_release_存在的同时,添加两个product flavors,demo和full将产生四个build variants,每个都有它自己的定制配置:

  • demoDebug
  • demoRelease
  • fullDebug
  • fullRelease
  • 基于buildType, 和productFlavor构建设定的Build variants
  • 主sourceSet,通常位于src/main/res
  • Library Project依赖,通过它们的aar bundle中的res entry提供资源。

按优先级从低到高的合并顺序为libraries/dependencies -> main src -> productFlavor -> buildType。

某些工程具有复杂的多维度的功能组合,但它们仍然表示相同的app。比如,除了有app的demo和full版本之外,某些游戏可能包含特定于一个特别的CPU/ABI的二进制文件。构建系统的灵活性使得为一个工程产生如下的这些build variants成为可能:

  • x86-demoDebug
  • x86-demoRelease
  • x86-fullDebug
  • x86-fullRelease
  • arm-demoDebug
  • arm-demoRelease
  • arm-fullDebug
  • arm-fullRelease
  • mips-demoDebug
  • mips-demoRelease
  • mips-fullDebug
  • mips-fullRelease

这个工程将由两个build types (debug_和_release)和二维的product flavors组成,二维中的一个维度是app type (demo或full),另一个是CPU/ABI(x86, ARM, or MIPS)。

源码目录

要构建你的app的每个版本,构建系统将结合如下这些目录里的源码和资源:

src/main/ - 主源码目录(所有variants共用的默认配置)

src// - 源码目录

src// - 源码目录

注意:build type和product flavor源码目录是可选的,因而Android Studio不会为你创建这些目录。你应该在给构建配置文件添加build type和product flavor时创建这些目录。如果这些目录不存在,则构建系统将不使用它们。

对于那些没有定义任何flavors的工程,构建系统使用_defaultConfig_设定,主app目录和默认的build type目录。比如,要在工程中没有product flavors的情况下产生默认的_debug_和_release_ build variants,构建系统使用:

  • src/main/ (默认配置)

  • src/release/ (build type)

  • src/debug/ (build type)

对于那些定义了一系列product flavors的工程,构建系统则合并build type,product flavor和主源码目录。比如,要产生_full-debug_ build variant,构建系统合并build type,product flavor和主源码目录:

  • src/main/ (默认配置)
  • src/debug/ (build type)
  • src/full/ (flavor)

对于那些使用了多个flavor维度的工程,针对每个维度构建系统合并一个flavor源码目录。比如,要产生_arm-demo-release_ build variant,构建系统合并:

  • src/main/ (默认配置)
  • src/release/ (build type)
  • src/demo/ (flavor - app type dimension)
  • src/arm/ (flavor - ABI dimension)

这些目录下的源代码会被一起用来为一个build variant产生输出。你可以在那些不会被用在相同variant的不同目录下包含具有相同名字的类。

构建系统也会把所有的manifests合并为一个单独的manifest,从而每个build variant可以在最终的manifest中定义不同的组件或权限。manifests合并的优先级从低到高排列为libraries/dependencies -> main src -> productFlavor -> buildType。

构建系统合并所有源码目录下的所有资源。如果同一个build variant的不同文件夹中包含了具有相同名字的资源,则优先级顺序如下:build type资源覆盖product flavor的那些资源,product flavor资源覆盖主源码目录下的资源,主源码目录下的资源覆盖库的资源。

注意:Build variants使你能够在你的app的不同版本间复用共用的activities,应用程序逻辑,和资源。

Done。

原文

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这