懒人Android开发。
最近做项目,一个项目(一套代码)针对多个客户,要出多个版本,但不同的客户需求导致项目代码有细微的不同,以及应用加载的资源图片都是不一样,如果仅仅是代码细微差别还好,但是资源图片加载的都不一样,这导致apk大包资源图片冗余大,这并不是我们所希望的。
android studio 项目里面的build.gradle我们并不陌生,但是如何高级运用,我相信有许多人和我一样,一脸懵逼。要利用好build.gradle,必须要对Groovy语言有一点基础,当然没有基础的也可以站在巨人的肩膀上依葫芦画瓢,也可以做一些简单的运用,当要根据自己的的项目以装逼的方式利用build.gradle配置文件对项目代码合理的编译打包,避免资源文件冗余,那必然会踩很多坑,我就是这么过来的.哈哈。
当然,我也不是你们心中的巨人,老菜苗一个,所以我也教不了你们Groovy,至于build.gradle的使用也是我花了一天网上学习+瞎折腾的.踩过的坑也是让自己汗颜.所以决定把我的build.gradle分享出来,作为你们的一个葫芦,尽情的去画吧。... ... 自己第一次写博客,有点啰嗦了.
通过build.gradle配置文件可以做很多事情,我下面列举一些常用的:1.自定义versionCode,versionName的生成规则
2.动态修改Manifest里面的属性值,比如AndroidManifest中的icon,label,<meta>标签值等
3.定制编译成功后的apk名称规则
4.添加自定义buildConfig字段(很有用)
5.自定义编译任务
6.添加自定义的目录
7.过滤拓展的自定义目录,过滤默认的资源图片等(很有用)
以上是我目前项目所运用到的,后面会有添加,废话不啰嗦,上代码:
----------------------------------------------- 废话都在代码里面了 ----------------------------------------------------
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion '25.0.0'
defaultConfig {
applicationId "com.android.tongxunlu"
minSdkVersion 19
targetSdkVersion 22
versionCode buildVersionCode()
versionName buildVersionName()
// 默认的配置
buildConfigField "int", "oem_type", "-1"
manifestPlaceholders = [label: "通讯录", icon: "@mipmap/ic_launcher", sharedUserId: "android.uid.system"]
}
//程序在buid的时候,会执行lint检查,有任何的错误或者警告提示,都会终止构建,我们可以将其关掉。
lintOptions {
abortOnError false
ignoreWarnings true
checkReleaseBuilds false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
// debug和release版本的签名
signingConfigs {
release {
storeFile file("D:/other/mysign/test.jks")
storePassword "12345678"
keyAlias "test"
keyPassword "123456"
}
}
buildTypes {//构建类型,通常有release和debug两种
release {
signingConfig signingConfigs.release
// minifyEnabled true //开启混淆
// shrinkResources true;//是否移除无用资源文件,shrinkResources依赖于minifyEnabled,必须和minifyEnabled一起用
zipAlignEnabled true //是否启用zipAlign压缩
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//混淆文件
}
debug {
signingConfig signingConfigs.release
zipAlignEnabled true //是否启用zipAlign压缩
}
// 定制生成apk的名称
applicationVariants.all { variant ->
// each遍历variant
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null) {
println "======outputFile.name======" + outputFile.name;
def fileName;
if (outputFile.name.endsWith('release.apk')) {
fileName = "tongxunlu${defaultConfig.versionName}_${variant.productFlavors[0].name}_release.apk";
} else if (outputFile.name.endsWith('debug.apk')) {
fileName = "tongxunlu${defaultConfig.versionName}_${variant.productFlavors[0].name}_debug.apk";
}
output.outputFile = new File(outputFile.name, fileName)
}
}
}
}
// OEM原始设备制造商{oem_type: 0康冠,1中电数码,2艾博德,3凯佳达,4富士康,5凌畅,6视美泰,7佳杰,8长虹}
// 代码里面可以针对oem_type进行逻辑分支
// 如果是大的逻辑差异,可以进行src分支,原理同sourceSets中res分支
productFlavors {
// debug
unsigned {// 没有板卡系统签名文件,打这个包
println "======unsigned======"
manifestPlaceholders = [sharedUserId: "com.android.tongxunlu"]
}
// 客户
KangGuan {// 0康冠
println "======KangGuan======"
manifestPlaceholders = [label: "连屏", icon: "@mipmap/ktc_ic_launcher"]
buildConfigField "int", "oem_type", "0"
}
ZhongDian {// 1中电数码
println "======ZhongDian======"
manifestPlaceholders = [label: "中电"]
buildConfigField "int", "oem_type", "1"
}
...
}
// 针对不同的客户,编译不同的目录,避免不必要的资源冗余
sourceSets {// 配置资源集
// 添加目录,编译的时候会把所加的目录编译进去
// main.res.srcDirs += ['src/main/res-kg']
// main.res.srcDirs += ['src/main/res-zd']
...
// 指定编译的目录(其中已经包括了默认的资源)
KangGuan.res.srcDirs = ['src/main/res-kg']
ZhongDian.res.srcDirs = ['src/main/res-zd']
...
}
}
allprojects {
// 注: 某些输入文件使用或覆盖了已过时的 API。
// 注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
// 注: 某些输入文件使用了未经检查或不安全的操作。
// 注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
// gradle.projectsEvaluated {
// tasks.withType(JavaCompile) {
// options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
// }
// }
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'de.hdodenhof:circleimageview:2.0.0'
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
compile 'com.mani:ThinDownloadManager:1.2.5'
// compile 'org.nanohttpd:nanohttpd:2.3.0'
compile 'com.google.android.exoplayer:exoplayer:r1.5.9'
compile 'com.android.support:support-v4:22.0.0'
compile files('libs/zxing.jar')
}
/** **********************************************************/
// 自定义编译后的版本号
def buildVersionCode() {
return Integer.parseInt(new Date().format("YYMMddHHmm"))
}
// 自定义编译后的版本名称
def buildVersionName() {
def date = new Date();
int ver = Integer.parseInt(date.format("YY")) - 17;// 17年基版本
int si = Integer.parseInt(date.format("MM"));
int on = Integer.parseInt(date.format("dd"));
return "1." + ver + "." + si + "." + on;// 老版本1.开头
}
/********************** gradle cmd ***************************/
//gradle assembleRelease // 构建productFlavors下所有Variant Release版本
//gradle assembleDebug // 构建productFlavors下所有Variant Debug版本
//gradle assemble[productFlavors.name] // 构建productFlavors下name的Variant Release和Debug版本
//gradle assemble[productFlavors.name]Relase // 构建productFlavors下name的Variant Releaseg版本
//gradle assemble[productFlavors.name]Debug // 构建productFlavors下name的Variant Debug版本
==============================排版什么的请忽略,下面直接上截图============================
1.添加的目录分支,可以针对不同的客户选择性编译目录文件,如果指定一个目录,其他目录分支没有指定,那只会把指定的目录和默认的目录一起打包到apk中。
如果res-kg/drawable下的文件名和res/drawable下的文件名同名,打包的时候res-kg/drawable会替换掉res/drawable下的同名文件,这也正是实现了一个布局文件可以根据打包所指定的Flavors不同而读取的资源也不同.
2.gradle常用命令,使用前需配置好gradle的环境变量。
使用以下命令前最好执行下 gradle clean 命令。
3.通过AS去选择编译打包apk
4.通过buildConfigField自定义自动生成的BuildConfig类的成员常量
5.动态修改AndroidManifest.xml里面的一些值,如icon,label,<meta-data>标签值等
6.生成的apk名称,效果图
毫无排版,看不懂的请见谅,老菜苗觉得关键的都毫无保留的贴出来了.O(∩_∩)O哈哈~
老菜苗还有很多Android开发干货等有时间后期会分享给大家,谢谢大家!!!