现在随着友盟这类统计工具在项目中集成,根据不同渠道打不同的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有:
- assemble
- build
- check
- clean
根据名字基本就能知道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://*.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") } }
Product flavors
如果你一个项目想要生成不同的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下了!