什么是Gradle

你可以看一下Gradle主页

简单来说,Gradle是一个自动化编译部署测试工具。Gradle内容很广,还有专门的书介绍Gradle。而Android Studio使用的是Gradle中的一部分功能。

build.gradle

build.gradle就是Android Studio使用的Gradle文件,下面是一个最简单的build.gradle示例:

  1. buildscript {
  2.     repositories {
  3.         mavenCentral()
  4.     }
  5.     dependencies {
  6.         classpath 'com.android.tools.build:gradle:0.6.+'
  7.     }
  8. }
  9. apply plugin: 'android'
  10. android {
  11.     compileSdkVersion 17
  12. }
复制代码

buildscript {...} 配置编译代码,这部分基本上不用怎么编辑;

apply plugin: 'android' 是表示用android插件;

android {...} 就是android插件的配置了。具体配置内容以及取值可以看这里

Build Task

Gradle中用Task来代表一系列操作,有点类似于Makefile中的Target。常见的Tasks有:

  • assemble
  • build
  • check
  • clean

根据名字基本就能知道Task作用,其中build = assemble + check。

执行task直接就是在命令行执行gradle [task],例如: gradle assemble

gradle assembleRelease

Build参数配置

Gradle脚本中的参数是DSL规范的,即使用的是类似于Java包名的方式:

  1. a.b.c = 1
  2. a {
  3.     b {
  4.       c 1        
  5.     }
  6. }
复制代码

上面两种方式表示的是一个意思。 可以配置的参数这里不做详述,请到http://tools.android.com/tech-docs/new-build-system/user-guide查阅。

下面讲几个主要使用的参数。

Build Types

TODO

Signing Configurations

在生成APK的时候,有一步是用一个Key给APK签名,关于签名的配置项都在signingConfigs中:

  1. signingConfigs {
  2.     myConfig {
  3.         storeFile file("path-to-keystore")
  4.         storePassword "******"
  5.         keyAlias "******"
  6.         keyPassword "******"
  7.     }
  8. }
复制代码

然后在编译类型中引用:

  1. buildTypes {
  2.     release {
  3.         ...
  4.         signingConfig signingConfigs.myConfig
  5.     }
  6. }
复制代码

这样签名的配置就好了。不过按上文配置,有一个问题:build.gradle经常是会提交到代码管理系统中,而显然把key明文放在代码库里不怎么安全(特别如果你写的是开源项目)。一个替代的方案是输入密码,或者将密码存储在环境变量中,可以参看这个链接:http://stackoverflow.com/questio ... k-file-using-gradle

  1. ... 
  2. signingConfigs {
  3.     release {
  4.         storeFile file(System.getenv("KEYSTORE"))
  5.         storePassword System.getenv("KEYSTORE_PASSWORD")
  6.         keyAlias System.getenv("KEY_ALIAS")
  7.         keyPassword System.getenv("KEY_PASSWORD")
  8.     }
  9. }
复制代码

Product flavors

如果你一个项目想要生成不同的APK包,有不同的包名,或者不同的资源,那么这就是使用Product flavors的时候了。

  1. android {
  2.     ....
  3.     productFlavors {
  4.         flavor1 {
  5.             packageName "com.example.flavor1"
  6.             versionCode 20
  7.         }
  8.         flavor2 {
  9.             packageName "com.example.flavor2"
  10.             minSdkVersion 14
  11.         }
  12.     }
  13. }
复制代码

上面的示例会生成两个不同的APK包,有着不同的包名以及属性。Product flavors里边可以设置的属性,参照http://tools.android.com/tech-docs/new-build-system/user-guide

友盟多渠道打包

看了上面这么多,现在来一个示例:写一个build.gradle完成友盟多渠道打包。 友盟渠道区分是通过在AndroidManifest.xml的<meta-data>实现的:

  1. <meta-data android:value="UMENG_CHANNEL_VALUE" android:name="UMENG_CHANNEL"/>
复制代码

所以基本的思路就是,在打包的时候替换AndroidManifest.xml中的字符串以打出不同的APK包。 build.gradle关键部分如下:

  1. android {
  2.     compileSdkVersion 19
  3.     buildToolsVersion '19.0.0'
  4.     defaultConfig {
  5.         minSdkVersion 7
  6.         targetSdkVersion 19
  7.     }
  8.     // 签名信息,都存在环境变量中
  9.     signingConfigs {
  10.         release {
  11.             storeFile file(System.getenv("KEYSTORE"))
  12.             storePassword System.getenv("KEYSTORE_PASSWORD")
  13.             keyAlias System.getenv("KEY_ALIAS")
  14.             keyPassword System.getenv("KEYSTORE_PASSWORD")
  15.         }
  16.     }
  17.     buildTypes {
  18.         release {
  19.             runProguard true
  20.             proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
  21.             signingConfig signingConfigs.release  //使用上述签名信息
  22.         }
  23.     }
  24.     productFlavors {
  25.         defaultFlavor {
  26.             proguardFile 'proguard-rules.txt'
  27.         }
  28.         // 需要打不同的版本
  29.         xiaomi {
  30.         }
  31.         LeTv {
  32.         }
  33.     }
  34. }
  35. // 下面这段代码摘自 <a href="https://github.com/umeng/umeng-muti-channel-build-tool/tree/master/Gradle" target="_blank" style="color: rgb(0, 136, 204); text-decoration: none;">https://github.com/umeng/umeng-muti-channel-build-tool/tree/master/Gradle</a>
  36. // 实现用productFlavor名字替换AndroidManifest.xml 中的 UMENG_CHANNEL_VALUE 字符串
  37. android.applicationVariants.all { variant ->
  38.     variant.processManifest.doLast{
  39.         copy{
  40.             from("${buildDir}/manifests"){
  41.                 include "${variant.dirName}/AndroidManifest.xml"
  42.             }
  43.             into("${buildDir}/manifests/$variant.name")
  44.             filter{
  45.                 String line -> line.replaceAll("UMENG_CHANNEL_VALUE", "${variant.productFlavors[0].name}")
  46.             }
  47.             variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")
  48.         }
  49.     }
  50. }
复制代码

在修改完build.gradle之后,需要使用Android Studio的sync Project with gradle files功能同步工程设置。 之后就在Android Studio的Terminal中输入gradle build(windows是gradlew build),稍等片刻,所有生成的APK都在你工程的build/apk下啦!