本人用Android studio也已经一年多了,现在回过头来写写gradle相关的知识点,希望能给新手带来些许帮助,大神勿喷
1、gradle的基本配置
每次新建一个module,在build.gradle文件中,都会自动生成如下配置:
我们知道,在eclipse开发中,应用程序包名是由manifest下的package属性决定的:
然而在使用gradle构建的项目中,却多了一个applicationId属性,并且应用程序包名是由这个applicationId决定的:
defaultConfig {
applicationId "com.xxx.xxxx"
}
通常gradle中的 applicationId 和Manifest中的 package 是一样的,当然也可以不一样,官方对两者的界定给出的解释是:
applicationId是应用在商店的唯一标识;
package是引用资源的路径名,也就是R文件的包名.
2、gradle的签名配置
关于签名的概念不懂得,可以参考这篇blog:Android从零单排之签名打包
签名配置的语法在项目的【Project Structure】中可以找到:
如上图所示补全签名信息就可以在build.gradle中自动生成签名配置.
当然,更一般的配置方法是在build.gradle中手动书写签名配置:
android {
signingConfigs {
config_release {
keyAlias 'releaseKey'
keyPassword '123456'
storePassword '123456'
storeFile file('key/releaseKey.jks')
}
config_debug {
keyAlias 'debugKey'
keyPassword '123456'
storePassword '123456'
storeFile file('key/debugKey.jks')
}
}
......//省略其他配置
}
这里配置了两个签名,签名文件都放在app下面的key文件夹中,所以使用的是相对路径.
如果将签名密码直接写在gradle中显然并不是很安全的做法,我们最好还是做点保密措施:在gradle中隐藏Keystore密码
3、 配置buildTypes
语法在项目的【Project Structure】中也能找到:
这里可配置的信息很多,一般是在buildTypes{ }里面配置两个(release和debug):
buildTypes {
release {
signingConfig signingConfigs.config_release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.config_debug
}
}
4、 配置productFlavor
多渠道打包,关键就在于productFlavor:
productFlavors {
flavor_1 {
minSdkVersion 14
signingConfig signingConfigs.config_release
targetSdkVersion 23
versionCode 2
versionName '2.0.1'
applicationId 'com.huaihuai.android.one'
}
flavor_2 {
minSdkVersion 10
signingConfig signingConfigs.config_debug
versionCode 1
versionName '1.0.0'
applicationId 'com.huaihuai.android.two'
}
}
我们这里给不同渠道配置不同的applicationId,就可以打包出多个不同渠道不同包名的apk.
这样有一个应用场景就是:包名不同的apk可以共存在一个手机上,利用这点我们可以在测试机上运行多个版本的apk以方便测试.
productFlavors{ } 与 buildTypes{ }里面的配置是多对多的关系.
比如:
android {
buildTypes {
release {...}
debug {...}
}
productFlavors {
flavor_1 {...}
flavor_2 {...}
}
}
这时的配置可以打出4个apk,分别是:
#5、打包命令
强烈推荐使用gradlew命令行进行打包,因为gradle下很多方便的配置只有以命令行的方式才能正常打包,后面会讲到.
比如我们打包flavor_1渠道下对应的release和debug版本:
当然,我们也不用去背这些gradle命令,因为在Android studio的右侧会有【Gradle】tab页面,里面包含了我们常用的命令:
6、manifest占位符
在打包多个版本的时候,会遇到修改应用名称等需求。不同的flavor有要求不同的名称. 此时可以在Manifest文件中使用占位符,然后在build.gradle中替换占位符就行了.
首先定义占位符:
在build.gradle中替换:
buildTypes {
release {
signingConfig signingConfigs.config_release
minifyEnabled false
manifestPlaceholders = [APP_NAME: "@string/app_name1"]
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.config_debug
manifestPlaceholders = [APP_NAME: "@string/app_name2"]
}
}
productFlavors {
flavor_1 {
minSdkVersion 14
signingConfig signingConfigs.config_release
targetSdkVersion 23
versionCode 2
versionName '2.0.1'
applicationId 'com.huaihuai.android.1'
manifestPlaceholders = [APP_NAME: "@string/app_name1"]
}
flavor_2 {
minSdkVersion 10
signingConfig signingConfigs.config_debug
versionCode 1
versionName '1.0.0'
applicationId 'com.huaihuai.android.2'
manifestPlaceholders = [APP_NAME: "@string/app_name2"]
}
}
如上,如果在productFlavors和buildTypes里面都进行了替换,那么是以productFlavors里面的为准.
如果不区分productFlavors和buildTypes的话,只是单纯修改应用名称的话,也可以在defaultConfig里进行替换:
defaultConfig {
applicationId "com.huaihuai.android"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
manifestPlaceholders = [APP_NAME: "@string/app_name"]
}
其实defaultConfig也是productFlavors的一个子集.
7、添加自定义字段
我们有时候需要运行的时候有不同的表现.
比如,release版本不显示log信息,debug版本显示log信息
这时候我们可以通过buildConfigField、resValue在gradle里面自定义一些字段:
buildConfigField "boolean", "showLog", '"false"'
resValue "String", "build_time", '"11110000"'
添加完毕之后,就可以在代码中使用了:
System.out.println(BuildConfig. showLog);
System.out.println(getString(R.string.build_time))
注意两者使用方法并不相同,resValue定义的字段更像是资源文件*.xml下定义的字段,此外它们还有以下区别:
1、buildConfigField可定义字段为基本数据类型
2、buildConfigField定义的字段会显示在BuildConfig类中
3、resValue可定义字段有:string(待补充)
4、resValue定义的字段会显示在generated.xml中
8、动态设置一些额外信息
假如想把当前的编译时间、编译的机器、最新的commit版本添加到apk,而这些信息又不好写在代码里,强大的gradle给了我创造可能的自信:
android {
defaultConfig {
resValue "string", "build_time", buildTime()
resValue "string", "build_host", hostName()
resValue "string", "build_revision", revision()
}
}
def buildTime() {
return new Date().format("yyyy-MM-dd HH:mm:ss")
}
def hostName() {
return System.getProperty("user.name") + "@" + InetAddress.localHost.hostName
}
def revision() {
def code = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = code
}
return code.toString()
}
这个地方,如何从命令行读取返回结果,很有意思.
9、给自己留个”后门”: 点七下
为了调试方便,我们往往会在debug版本留一个显示我们想看的界面(记得之前微博的一个iOS版本就泄露了一个调试界面),如何进入到一个界面,我们可以仿照android开发者选项的方式,点七下才显示,我们来实现一个:
private int clickCount = 0;
private long clickTime = 0;
sevenClickView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (clickTime == 0) {
clickTime = System.currentTimeMillis();
}
if (System.currentTimeMillis() - clickTime > 500) {
clickCount = 0;
} else {
clickCount++;
}
clickTime = System.currentTimeMillis();
if (clickCount > 6) {
// 点七下条件达到,跳到debug界面
}
}
});
release版本肯定是不能暴露这个界面的,也不能让人用am在命令行调起,如何防止呢,可以在release版本把这个debug界面的exported设为false.
10、自定义导出APK的名称
两种方式实现:
/*applicationVariants.all {
variant ->
variant.outputs.each {
output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def apkType = ""
if (variant.flavorName.equals("flavor_1")) {
apkType = "flavor_1"
} else if (variant.flavorName.equals("flavor_2")) {
apkType = "flavor_2"
}
def fileName = new File(output.outputFile.getParent(),
"app-" + apkType + "-${variant.versionName}.apk")
output.outputFile = fileName
}
}
}*/
applicationVariants.all {
variant ->
variant.outputs.each {
output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = outputFile.name.replace(".apk",
"-${defaultConfig.versionCode}-${defaultConfig.versionName}.apk")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
这里就不多讲了,大家运行测试一下就明白了.
至此,文章结束,希望此文能帮助到你,如果对此文有不同见解,欢迎直接评论!
参考文案:
Gradle的神奇之处
Android项目中如何用好构建神器Gradle?
Android 使用Android Studio + Gradle 或 命令行 进行apk签名打包