build.gradle的高级运用,通过Groovy语言合理的编译打包代码,避免资源文件冗余

懒人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
    }
    //  debugrelease版本的签名
    signingConfigs {
        release {
            storeFile file("D:/other/mysign/test.jks")
            storePassword "12345678"
            keyAlias "test"
            keyPassword "123456"
        }
    }
    buildTypes {//构建类型,通常有releasedebug两种
        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分支,原理同sourceSetsres分支
    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]          // 构建productFlavorsnameVariant ReleaseDebug版本
//gradle assemble[productFlavors.name]Relase    // 构建productFlavorsnameVariant Releaseg版本
//gradle assemble[productFlavors.name]Debug     // 构建productFlavorsnameVariant 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开发干货等有时间后期会分享给大家,谢谢大家!!!





展开阅读全文

没有更多推荐了,返回首页