现在随着友盟这类统计工具在项目中集成,根据不同渠道打不同的APK包也成为日常工作之一。神马?你还在手动改渠道号一个一个打包?!那你一定是个非常勤奋的程序员- -!正好尝试使用Android Studio,稍微了解了下Android Studio的使用的构建工具:Gradle。
什么是Gradle你可以看一下Gradle主页。
简单来说,Gradle是一个自动化编译部署测试工具。Gradle内容很广,还有专门的书介绍Gradle。而Android Studio使用的是Gradle中的一部分功能。
build.gradlebuild.gradle就是Android Studio使用的Gradle文件,下面是一个最简单的build.gradle示例:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
}
}
apply plugin: 'android'
android {
compileSdkVersion 17
}
buildscript {...} 配置编译代码,这部分基本上不用怎么编辑;
apply plugin: 'android' 是表示用android插件;
android {...} 就是android插件的配置了。具体配置内容以及取值可以看这里
Build TaskGradle中用Task来代表一系列操作,有点类似于Makefile中的Target。常见的Tasks有:
根据名字基本就能知道Task作用,其中build = assemble + check。
执行task直接就是在命令行执行gradle [task],例如: gradle assemble
gradle assembleRelease
Build参数配置Gradle脚本中的参数是DSL规范的,即使用的是类似于Java包名的方式:
a.b.c = 1
a {
b {
c 1
}
}
上面两种方式表示的是一个意思。 可以配置的参数这里不做详述,请到http://tools.android.com/tech-docs/new-build-system/user-guide查阅。
下面讲几个主要使用的参数。
Build TypesTODO
Signing Configurations在生成APK的时候,有一步是用一个Key给APK签名,关于签名的配置项都在signingConfigs中:
signingConfigs {
myConfig {
storeFile file("path-to-keystore")
storePassword "******"
keyAlias "******"
keyPassword "******"
}
}
然后在编译类型中引用:
buildTypes {
release {
...
signingConfig signingConfigs.myConfig
}
}
这样签名的配置就好了。不过按上文配置,有一个问题:build.gradle经常是会提交到代码管理系统中,而显然把key明文放在代码库里不怎么安全(特别如果你写的是开源项目)。一个替代的方案是输入密码,或者将密码存储在环境变量中,可以参看这个链接:
http://stackoverflow.com/questio ... k-file-using-gradle
...
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE"))
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
如果你一个项目想要生成不同的APK包,有不同的包名,或者不同的资源,那么这就是使用Product flavors的时候了。
android {
....
productFlavors {
flavor1 {
packageName "com.example.flavor1"
versionCode 20
}
flavor2 {
packageName "com.example.flavor2"
minSdkVersion 14
}
}
}
上面的示例会生成两个不同的APK包,有着不同的包名以及属性。Product flavors里边可以设置的属性,参照http://tools.android.com/tech-docs/new-build-system/user-guide。
友盟多渠道打包看了上面这么多,现在来一个示例:写一个build.gradle完成友盟多渠道打包。 友盟渠道区分是通过在AndroidManifest.xml的<meta-data>实现的:
<meta-data android:value="UMENG_CHANNEL_VALUE" android:name="UMENG_CHANNEL"/>
所以基本的思路就是,在打包的时候替换AndroidManifest.xml中的字符串以打出不同的APK包。 build.gradle关键部分如下:
android {
compileSdkVersion 19
buildToolsVersion '19.0.0'
defaultConfig {
minSdkVersion 7
targetSdkVersion 19
}
// 签名信息,都存在环境变量中
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE"))
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEYSTORE_PASSWORD")
}
}
buildTypes {
release {
runProguard true
proguardFile getDefaultProguardFile('proguard-android-optimize.txt')
signingConfig signingConfigs.release //使用上述签名信息
}
}
productFlavors {
defaultFlavor {
proguardFile 'proguard-rules.txt'
}
// 需要打不同的版本
xiaomi {
}
LeTv {
}
}
}
// 下面这段代码摘自 <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>
// 实现用productFlavor名字替换AndroidManifest.xml 中的 UMENG_CHANNEL_VALUE 字符串
android.applicationVariants.all { variant ->
variant.processManifest.doLast{
copy{
from("${buildDir}/manifests"){
include "${variant.dirName}/AndroidManifest.xml"
}
into("${buildDir}/manifests/$variant.name")
filter{
String line -> line.replaceAll("UMENG_CHANNEL_VALUE", "${variant.productFlavors[0].name}")
}
variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")
}
}
}
在修改完build.gradle之后,需要使用Android Studio的sync Project with gradle files功能同步工程设置。 之后就在Android Studio的Terminal中输入gradle build(windows是gradlew build),稍等片刻,所有生成的APK都在你工程的build/apk下了!