Gradle for Android 简要记录

本文介绍Gradle在Android项目中的应用,包括基础概念、常用命令、自定义构建等。涵盖依赖管理、多渠道打包、签名配置及高级构建技巧。

一.基础概念

  1. Gradle 有约定优于配置的原则,即为设置和属性提供默认值。

  2. Gradle 是基于 Groovy 领域专用语言 DSL.

  3. 在 Gradle 中,最重要的两个概念是项目和任务。每一次构建都包括至少一个项目,每一个项目又包括多个任务。每个 build.gradle 文件都代表着一个项目,任务定义在构建脚步里。

  4. 源集 source set
    一 个源集是一组源文件,它们会一起执行和编译。
    在 Android 中,main 就是一个源集。
    这里写图片描述

二. 常用命令

./gradlew assemble 生成 releas 和 debug 版本, 如果是配置了多渠道,则每个渠道都会生成 Release 和 Debug 版本

./gradlew assembleRelease 则会为每个渠道生成 Release 包, ./gradlew assembleDebug 类似

// 可以指定渠道版本
./gradlew assembleXiaomiDebug

运行测试,遇到问题会立即停止
./gradlew test
如果是想运行特点的 flavor
./gradlew testXiaomiDebug , 例子
// 如果遇到问题,还想继续执行
./gradlew test -continue
只针对一个特定的测试类, 例子
./gradlew testDebug –test=”*.LogicTest”

MyApp
|
|—- build.gradle
|—- settings.gradle
|
—- app
|
— build.gradle
例子
这里写图片描述

1. settings.gradle
settings 在初始化阶段被执行,定义包含的模块。
例如这包含 app 和 mylibrary
![这里写图片描述](https://img-blog.youkuaiyun.com/20170527221558196?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXhodWFuZzIwMDg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2. 顶层构建文件

. 在项目中,所有模块的配置参数都在顶层的 build.gradle 文件中配置。
如果在 build.gradle 中定义了一些属性,在 manifest 文件中不必再定义,如果构建文件中不包含某个属性,manifest 中该属性就会被用作后备。

. 任务 task
(1). assemble: 为每个构建版本构建一个 APK, 任务默认依赖于 assembleDebug 和 assembleRelease,如果执行命令./gradlew assemble 会生成 release 和 debug 两个 apk.

(2). clean: 删除所有的构建内容;

(3). check: 运行 Lint 检查,如果 Lint 发现一个问题,则可终止构建;

(4). build: 同时运行 assemble 和 check

./gradlew check 会生成一份 Lint 报告,在 app/build/outputs 目录下,名称为 lint-results.html, 该报告包含所有的警告和错误,以及一份详细的说明和一个相关文档的连接。
这里写图片描述

自定义构建

. BuidConfig 的设置
可以在构建类型 buildTypes 中设置 releas 和 debug 版本同的信息, 例如配置不同的 url

    // 构建类型
    buildTypes {
        release {
            minifyEnabled false  // 是否开启混淆
            shrinkResources false  // 自动缩减资源,需要同时与 minifyEnabled 开启
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'   // 混淆配置文件
            // 配置log,在 Release 版本中不打印,
            buildConfigField "boolean", "LOG_CALLS", "false";
            // 配置不同的 URL
            buildConfigField "String", "API_URL", "\"Http://example.com/api\""
        }

        debug {
            buildConfigField "boolean", "LOG_CALLS", "true";
            buildConfigField "String", "API_URL", "\"Http://texst.example.com/api\""
        }
    }

在 java 代码中 BuildConfig.API_URL 引用即可;

. 项目范围的设置
可以在顶层的 build.gradle 中添加一个自定义属性的 ext 代码块

// 自定义属性
ext {
    compileSdkVersion = 25
    buildToolsVersion = "25.0.3"

}

然后在模块的的 build.gradle 中使用 rootProject 来获取属性

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
  }

三. 基本自定义构建

1. 依赖仓库

Gradle 支持三种不同的依赖仓库: Maven, Ivy 和静态文件或文件夹.
在顶项目根目录下的 build.gradle

allprojects {
    repositories {
        // jcenter 仓库
        jcenter()
        // Maven Central
        mavenCentral()
        // 本地 Maven 仓库
        mavenLocal()
        // 自有的 Maven 插件, 例子
        maven {
            url "http://repo.acmecorp.com/maven2"
        }
        // 团队自己的仓库
        maven {
            url "http://repo.acmecorp.com/maven2"
            credentials {
                username '****'
                password '*****'
            }
        }
    }
}

四. 依赖管理

1. 本地依赖和项目依赖
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])  // 本地依赖
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    // 依赖项目
    compile project(':mylibrary')

    compile 'com.android.support:appcompat-v7:25.3.1'

    // 测试
    testCompile 'junit:junit:4.12'
    // 可以针对特定的 flavor 添加 Junit
    testXiaomiCompile 'junit:junit:4.12'
}

上面我们看到有 compile, 和 testCompile 其实 gradle 可以进行不同的配置
. compile 是默认配置,在编译主应用时包含所有的依赖。

. testComplie 测试依赖

. 针对特定的 variant 的依赖配置,这里的例子是 Xiaomi

.apk, 该依赖只会 被打包到 APK, 而不会添加到编译路径

.provided 与 apk 刚好相反,其依赖不会被打包进 APK.

五. 创建构建 Variant

1. 构建类型

构建类型除了 Release 和 debug 外,可以自定义类型

    // 构建类型
    buildTypes {
        release {
            minifyEnabled false  // 是否开启混淆
            shrinkResources false  // 自动缩减资源,需要同时与 minifyEnabled 开启
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'   // 混淆配置文件
            // 配置log,在 Release 版本中不打印,
            buildConfigField "boolean", "LOG_CALLS", "false";
            // 配置不同的 URL
            buildConfigField "String", "API_URL", "\"Http://example.com/api\""
            // 添加签名信息
//            signingConfig signingConfigs.releas
            // 指定渠道产品特定签名
//            productFlavors.xiaomi.signingConfig signingConfigs.xiaomi
        }

        debug {
            buildConfigField "boolean", "LOG_CALLS", "true";
            buildConfigField "String", "API_URL", "\"Http://texst.example.com/api\""
//            signingConfig signingConfigs.debug
            // 开启测试覆盖率
//            testCoverageEnabled = true
        }

        // 自定义构建类型(命令行可以 ./gradlew assembleStaging)
        staging {
            staging.initWith(buildTypes.debug) // 复制一个已经存在的构建类型所有属性,可以重写,例如下面的 API_URL
            applicationIdSuffix ".staging"  // 生成的 applicationId 变成 包名.staging, 这里是  cash.juzhongke.com.gradledetaildemo.staging
            versionNameSuffix "staging"
            buildConfigField "String", "API_URL", "\"Http://staging.example.com/api\""
//            signingConfig signingConfigs.staging
        }
    }
2. 源集

当创建一个新的构建类型时,Gradle 也会创建一个新的源集。源集目录名称默认和构建类型相同。该目录不是在定义新的构建类型时自动创建的,需要在构建类型使用自定义的源码和资源之前,手动创建该源集目录。
这里写图片描述
上图除了标准的 debug 和 Release ,还有一个额外 staging 构建类型的目录结构。

使用不同源集目录,可以构建类型自己的属性,例如,我们可以定义不同的包名,
这里写图片描述

详情可参考美团技术团队的《美团Android自动化之旅—适配渠道包》

3.product flavor

可以构建不同版本,用于多渠道打包

 // 不同渠道版本
    productFlavors {
        commonsoon {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "commonsoon"]

            // 可以自定义自己的 applicationId
            applicationId 'cash.juzhongke.com.gradledetaildemo.commonsoon'
            versionCode 3
            minSdkVersion 23
        }
        zhushou91 {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "zhushou91"]
        }
        market360 {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "market360"]
        }
        xiaomi {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
        }
        wandoujia {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
        }
    }
4.构建 Variant

构建 variant 是构建类型和product flavor 结合的结果。点击 Android Studio 左下角的 Build Variant 可以看到
这里写图片描述

5. variant 过滤器

通过 variants 过滤器忽略一些 variant

android {
    // variant 过滤器,这里是忽略 xiaomi release 版本, 在 BuildVariants 中可以看到结果
    android.variantFilter { variant ->
        if (variant.buildType.name.equals('release')){
            variant.getFlavors().each(){ flavor ->
                if (flavor.name.equals('xiaomi')){
                    variant.setIgnore(true);
                }
            }
        }
    }
}

上面的例子是过滤掉 xiaomirelease 版本,在 Build Variant 中,我们就看不到了
这里写图片描述

这里的过滤在 Jenkins 集成的时候特别有用。

6. 签名配置

如果有一个付费版和免费版或针对不同用户的不同应用,可以为每个 flavor

    signingConfigs {
        releas {
            storeFile file(KEY_STORE_FIELD)
            keyAlias
            keyPassword
            storePassword
        }

        debug {
            storeFile file()
            keyAlias
            keyPassword
            storePassword
        }

        staging.initWith(signingConfigs.releas) // staging 和 release 版本一样的签名信息

        // 可以为特定的 flavor 签名
        xiaomi {
            storeFile file()
            keyAlias
            keyPassword
            storePassword
        }
    }

六. 创建任务和插件

加速多模块构建
在根目录下的 gradle.properities

# 并行构建项目, 可以加快构建项目
org.gradle.parallel=true

开启了虽然可以加快构建速度,有时候可能会失败。
使用命令行可以看到开启的信息

$ ./gradlew assemble
Parallel execution is an incubating feature.

七. 高级自定义构建

1. 使用任务来简化 release 过程

如果是配置签名

    signingConfigs {
        releas {
            storeFile file("release.keystore")
            keyAlias "Releasekey"
            keyPassword   "password"
            storePassword  "password"
        }

这样密码已明文方式存放,不安全。可以通过以 task 来构建
在项目的根目录下创建一个 private.properties 文件,然后添加属性;
这里写图片描述

然后在module 目录下的 builde.gradle 添加 task

// 定义一个任务来获取 Release Password
task getReleasePassword << {
    def keypassword = ''
    def storepassword = ''
    def keyalies = ''
    if (rootProject.file('private.properties').exists()){
        Properties properties = new Properties();
        properties.load(rootProject.file('private.properties')
                                      .newDataInputStream())
        keypassword = properties.getProperty('release.password')
        storepassword = properties.getProperty('release.storepassword')
        keyalies = properties.getProperty('release.keyalies')

    }

    // 如果password 为空,private.properties 文件找不到,则询问控制台用户输入
    if (!keypassword?.trim()){
        keypassword = new String(System.console().readPassword("\nWhat's the secret password?"))
    }

    android.signingConfigs.release.keyPassword = keypassword
    android.signingConfigs.release.storePassword = storepassword
    android.signingConfigs.release.keyAlias = keyalies
}

// 运行时才添加,相当于 Hook
tasks.whenTaskAdded { theTask ->
    if (theTask.name.contains("Release")){
        theTask.dependsOn "getReleasePassword"
    }
}

修改后的签名设置

    signingConfigs {
        release {
            storeFile file(KEY_STORE_FIELD)
        }

其中 KEY_STORE_FIELD 是 keystore 的路径,在 gradle.properties 上面设置

KEY_STORE_FIELD = E:\\work\\testkeystore\\gradleDemo.jks
2. 自动命名 apk

在 module 的 build.gradle 中

    // 自动命名 apk
    android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def file = output.outputFile
            output.outputFile = new File(file.parent,
                file.name.replace(".apk", "-${variant.versionName}.apk"))
        }
    }

这里在 jenkins 持续集成时会用到。

3. 缩减资源

自动缩减

    buildTypes {
        release {
            minifyEnabled false  // 是否开启混淆
            shrinkResources false  // 自动缩减资源,需要同时与 minifyEnabled 开启
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 
                                  'proguard-rules.pro'   // 混淆配置文件
            }
     }

手动缩减

    defaultConfig {
        applicationId "cash.juzhongke.com.gradledetaildemo"
        minSdkVersion 22
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        //  收到缩减 resConfigs 配置保留资源
        resConfigs "en", "cn", "da"    // 例如保留英语,中文,丹麦的字符串
        resConfigs "hdpi", "xhdpi", "xxhdpi"
    }

注:以上内容摘自《Gradle for Android 中文版》 一书

About This Book, Create custom Gradle tasks and plugins for your Android projects, Configure different build variants, each with their own dependencies and properties, Manage multi-module projects, and integrate modules interdependently, Who This Book Is For, If you are an experienced Android developer wanting to enhance your skills with the Gradle Android build system, then this book is for you. As a prerequisite, you will need some knowledge of the concepts of Android application development., What You Will Learn, Build new Android apps and libraries using Android Studio and Gradle, Migrate projects from Eclipse to Android Studio and Gradle, Manage the local and remote dependencies of your projects, Create multiple build variants, Include multiple modules in a single project, Integrate tests into the build process, Create custom tasks and plugins for Android projects, In Detail, Gradle is an open source build automation system that introduces a Groovy-based domain-specific language (DSL) to configure projects. Using Gradle makes it easy for Android developers to manage dependencies and set up the entire build process., This book begins by taking you through the basics of Gradle and how it works with Android Studio. Furthermore, you will learn how to add local and remote dependencies to your project. You will work with build variants, such as debug and release, paid and free, and even combinations of these things. The book will also help you set up unit and integration testing with different libraries and will show how Gradle and Android Studio can make running tests easier. Finally, you will be shown a number of tips and tricks on the advanced customization of your application's build process. By the end of this book, you will be able to customize the entire build process, and create your own tasks and plugins for your Gradle builds.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值