Android Gradle 必备实用技巧

公众号[飞雪无情],现在负责研发管理。《Android Gradle权威指南》作者,Android官方技术文档译者。 个人博客:www.flysnow.org

看了下GitChat的分享,关于移动开发的基本上没有,在这个移动互联网的时代,这有点不科学。我作为一名从J2EE转过来的Android开发老兵,写过一本《Android Gradle权威指南》,所以这次和大家分享一些关于Android Gradle的必备实用技巧,希望能抛砖引玉。本场Chat主要包括: 隐藏Android签名文件和密钥信息; 自动生成Android版本信息; 批量控制生成的APK文件名; 自动瘦身APK文件; 善用AndroidManifest占位符; 自动化多渠道快速打包APK。 当前内容版权归码字科技所有并授权显示,盗版必究。

文章正文

这篇《Android Gradle 必备实用技巧》不光介绍了很多技巧,更从原理和源代码上分析了这些技巧是如何实现的,利用了Android Gradle的哪些特性,Android Gradle又是如何实现的。通篇共2.2W多字,26页,所以比较长,希望大家能够认真读完,有问题可以评论回复,期待和大家一起交流。

什么是Gradle

Gradle是一款非常优秀的构建系统工具,它使用可以配置的DSL语言描述构建流程,同时允许我们使用原生的Java和Groovy编码的方式进行构建,所以相比Ant、Maven这些非常灵活。

在Gradle中,大部分的构建都是通过Gradle的插件来完成的,插件是Gradle非常好的一个设计,Gradle提供了一个核心可以扩展的平台,然后通过插件来扩展Gradle的能力,灵活方便。

Gradle本身提供了非常多的插件,比如java,war,scala等,可以满足我们的绝大多数需求。如果内置的插件不能满足需求,可以使用第三方开发的插件,甚至自己开发可以满足自己需求的插件。

如果没有梯子,下载不了Gradle,我这里有个自己搭建的镜像可以使用 http://mirrors.flysnow.org/

什么是Android Gradle

刚开始我们做Android开发的时候,采用的是Eclipse+Ant的构建方式,后来Android团队打算采用基于IDEA的Android Studio的时候,采用了Gradle进行构建,为了能和Android Studio进行无缝整合,Android团队开发了Android Gradle这个Gradle的第三方插件,用于Android的开发构建。使用Android Gradle,我们可以更好的:

  1. 代码和资源的复用
  2. 很方便的创建App的衍生版本
  3. 可以满足自定义、扩展,而且非常容易
  4. 当然不能少的,可以和Android Studio无缝整合

Android团队开发了三个Android Gradle插件,但是他们都属于一套代码库。这三个插件名字分别为:

  1. com.android.application
  2. com.android.library
  3. com.android.library

从名字上看,其实他们分别对应我们Android的 Android App开发,Android Lib库开发以及Android Test测试工程的开发。

使用这三个插件也非常容易,和Gradle使用其它插件的方式一样,因为这是一个非内置自带的,第三方插件,所以我们首先得声明classpath的依赖,才可以使用,和jdk的classpath很像。

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

我们配置里仓库为jcenter,这样当我们配置依赖的时候,gradle就会去这个仓库里寻找我们的依赖。

然后我们在dependencies{}配置里我们需要的是Android Gradle2.2.3版本的插件。

buildscript{}这部分配置可以写到根工程的build.gradle脚本文件中,这样所有的子工程就不用重复配置了。 以上配置好之后,我们就可以应用我们的Android Gradle插件了。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"
}

android{}是Android插件提供的一个扩展类型,可以让我们自定义Android Gradle工程。compileSdkVersion是编译所依赖的Android SDK的版本,这里是API Level;buildToolsVersion是构建该Android工程所以的构建工具的版本。

以上应用的是一个App工程插件,应用Android Library插件和Android Test插件也类似的,只需要换成相应的id即可。

隐藏Android签名文件和密钥信息

很多团队一开始的成立的时候,十来个人,三五条枪,就开始创业了,每个组基本上就一个人,扛起所有。开始的时候,大家都不知道这款产品是否可以成功,所以也都没想那么多,只能小步快跑,快速迭代,占领市场,抢占用户,这才是最重要的。

随着产品越做越好,团队越来越大,组内成员越来越多,就开始注重团队协作,编码规范,性能安全,团队建设等等,因为只有做到这些,整个团队的工作效率和产出才能更高,才能有团队的威力,越到最后靠的是团队,而不是一个人。

说着说着快跑题了,扯到团队建设和管理上了O(∩_∩)O~,这个以后有时间再交流,大家有想法也可以加微信公公众号flysnow_org一起交流。说以上那么多,就是现在团队大了,人多了,要正规了。

以前我们都是把App的签名证书和相关密钥放在项目中,托管在git上,这样做非常方便,可以直接访问打包,并且借助git这个代码管理平台维护管理。但是签名信息这个是我们应用非常重要的信息,属于公司重要的资源,所以我们要做到分级管理,保证安全,这也是公司保密措施的一部分,所以基于此,签名信息需要隐藏,但是又可以让大家都可以使用这个签名打包。

签名信息既然不能放在项目中,那么就需要有个地方存放他们,既然不能在每个开发者的电脑上,那就只能放到构建的服务器上,所以要实现这个,你还得有自己的专门用于打包发版的服务器,我们把签名文件和密钥信息放到服务器上,在打包的时候去读取即可,下面我们以使用环境变量的方式为例,当然还有更多方式,比如配置文件等等。

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    signingConfigs {
        def appStoreFile = System.getenv("STORE_FILE")
        def appStorePassword = System.getenv("STORE_PASSWORD")
        def appKeyAlias = System.getenv("KEY_ALIAS")
        def appKeyPassword = System.getenv("KEY_PASSWORD")
        release {
            storeFile file(appStoreFile)
            storePassword appStorePassword
            keyAlias appKeyAlias
            keyPassword appKeyPassword
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            zipAlignEnabled true
        }
    }
}

然后我们在打包的机器上配置以上环境变量即可,window和linux的方式不一样,关于配置环境变量这一块的知识,大家可以自行google一下。

如果你是使用Jenkins这类CI打包,以Jenkins,它的配置里就可以指定Jenkins使用的环境变量,这样我们就不用区分linux和window了,只需要在Jenkins里配置即可。

以上配置好之后,我们就可以进行打包使用了,签名信息也做了隐藏,看到这里,相信大家也意识到了一个问题,那就是每个开发者电脑上并没有如上的环境变量配置,因为签名信息对他们是隐藏的,那么他们如何进行打包测试呢?这就需要我们两个一个debug签名上场了,我们直接使用android自己提供的debug签名即可,因为我们需要的是签名,保证可以生成App测试(非debug调试)即可,比如给测试。

首先我们要从我们自己的电脑目录上提取出来Android自带的debug签名,一般在你的${HOME}/.android/目录下,找到后拷贝到我们的工程目录下,其次找到他们的签名信息,比如密码,key等,这是公开的,我们可以参考Android文档。

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    signingConfigs {
        def appStoreFile = System.getenv("STORE_FILE")
        def appStorePassword = System.getenv("STORE_PASSWORD")
        def appKeyAlias = System.getenv("KEY_ALIAS")
        def appKeyPassword = System.getenv("KEY_PASSWORD")

        //当不能从环境变量里获取到签名信息的时候,就使用项目中带的debug签名
        if(!appStoreFile||!appStorePassword||!appKeyAlias||!appKeyPassword){
            appStoreFile = "debug.keystore"
            appStorePassword = "android"
            appKeyAlias = "androiddebugkey"
            appKeyPassword = "android"
        }
        release {
            storeFile file(appStoreFile)
            storePassword appStorePassword
            keyAlias appKeyAlias
            keyPassword appKeyPassword
        }
    }
}

关键的逻辑就是在signingConfigs中加了判断代码,如果签名信息四要素中的任何一个没有获取到,就使用默认的签名信息,这样当我们在打包服务器进行打包的时候就会使用正式发布的签名,因为我们已经在服务器上配置了签名信息的环境变量;当每个开发者自己生成Release包的时候,因为本机没有配置,就使用默认的签名。

假如有的开发者有时候也需要使用正式发布的签名打正式的包,用于升级测试等目的,也是可以做到的,比如Jenkins,给每个开发者开放一个账号,他们自己新建个Job就可以打正式的包了,打了之后可以在生成的构建里下载。

这里要隐藏我们的签名信息,既能保证签名信息的安全性,又可以进行正式的打包,其中的关键点是一个专有的打包服务器,如果你们公司还没有的话,赶紧试试吧,好处多多,从这个小技巧也可以看到Gradle的灵活性,我们和编写Java代码一样编写我们的构建打包流程。

自动生成版本信息

每一个App都会有一个版本号,这样用户就知道自己安装的应用是哪个版本,是不是最新版,有了问题,也可以找客服报上自己的版本,让客服有针对性的帮用户解决问题。

一般的版本有三部分构成:major.minor.patch,第一个是主版本号,第二个是副版本号,第三位补丁号,这种我们常见的见识1.0.0这样的,当然也有两位的1.0,对应major.minor,这里我们以三位为例。

原始的版本信息

隐藏内容 支付可见
购买文章 ¥9
订阅频道首月仅需 12 元/月,预计可省 1288 元
¥9
¥9购买
订阅频道免费读
× 订阅 Java 精选频道
首次订阅 ¥ 元/月 15元/月
订阅即可免费阅读所有精选内容