Android Gradle学习(九):有用的小技巧

现在的Android工程都是采用 gradle 来构建的,从早期的单一工程架构(一个项目只有一个主 module),到现在的组件化架构(一个项目包含有多个module),项目结构越来越复杂,在这里陆续记录一些挺有用的小技巧。

1. resolutionStrategy 统一全局第三方库版本

resolutionStrategy 顾名思义“解析策略”,也就是说可以在 gradle 解析各种依赖库时,配置一些解析策略。

1.1 resolutionStrategy.force

我们在开发的过程当中,会依赖使用各种第三方库,比如说最常见的 appcompat-v7 库,不仅我们自己的代码里会依赖该库,而且有可能我们依赖的第三方库也会依赖该库,但是不同的地方依赖该库的版本号都有可能不一致,这样在编译的时候,整个项目当中会出现各种不同版本号的 appcompat-v7 库,编译的时候可能会报错。我们不可能修改第三方库里对 appcompat-v7 库依赖的版本号,那么我们可以通过 resolutionStrategy.force 来强制编译时统一库的版本号。

android {
    configurations.all {
        resolutionStrategy {
            force 'com.android.support:appcompat-v7:28.0.0'
            force 'com.android.support:support-v4:28.0.0'
        }
    }
}

1.2 resolutionStrategy.dependencySubstitution

还有一种这样的情形,假设一个第三方工具库叫 org.gradle:util:3.0,除了我们自己的项目以及部分第三方库也有依赖它,但是在实际使用的过程当中,发现该库有些功能不满足或者有bug,那这个时候该怎么办呢?一是提 issue 让该库的作者去修改,但是时间上来不及;二是源码拿过来本地进行修改,直接本地集成,但是要修改依赖方式,那么这个时候可以这样做:

假设我们本地 module 名称叫 :util

android {
    configurations.all {
        resolutionStrategy {
            //远程依赖替换成本地依赖
            substitute module('org.gradle:util:3.0') with project(':util')
            //也可以将远程依赖换成另外的远程依赖,假设我们修改过的代码发布到自己的 maven 中央仓库后叫:com.xxx.xxx:util:3.0
            //substitute module('org.gradle:util:3.0') with module('com.xxx.xxx:util:3.0') 
        }
    }
}

2. gradle.settingsEvaluated 在编译之前做一些初始化工作

之前接手过一个项目,是采用 react-native 框架进行开发的,熟悉前端以及 React 的同学都知道,项目 build 的第一步是先进行 npm install 或者 yarn 操作,这样所有依赖的第三方库都会下载到 node_modules 目录下面。在 react-native 当中,Android 工程会依赖 node_modules 目录下的原生 Android 代码,但是因为库的版本关系,每次我编译的时候,都会发现某个 module 中的 build.gradle 配置与主工程冲突,需要手动修改才能编译。需要注意的是,node_modules 目录是动态下载的第三方库,并不会被提交,也就是说每次执行 yarn 操作之后再编译 Android,都需要手动更改下这个目录下的库,非常繁琐。那么有没方法来自动帮我们解决这个问题,不用每次都要手动修改呢?答案是可以。gradle 有个生命周期钩子方法 gradle.settingsEvaluated,在 gradle configure 阶段之前让我们做一些处理。

在我们项目的 settings.gradle 文件的最开头加上该方法的监听,注意该方法必须加在 settings.gradle 文件中,在 build.gradle 里没用。以下是个范例:

gradle.settingsEvaluated {
    println "-------------settingsEvaluated start------------"
    //假设我们要修改的是 react-native-fs 这个库当中的 build.gradle 文件
    //先删除该文件
    delete("${rootDir}/../node_modules/react-native-fs/android/build.gradle")
    //我们将修改好的文件放到 ./replace-files/react-native-fs 这个目录当中
    //前面已经删除了目标文件,现在只需将我们需要的文件复制过去即可
    copy {
        from("./replace-files/react-native-fs/build.gradle")
        into("${rootDir}/../node_modules/react-native-fs/android")
    }
    println "-------------settingsEvaluated end------------"
}

执行打包命令 ./gradlew assembleRelease 等的时候,一开始就会执行以上代码,自动帮我们做好这些事情。

除此之外,还可以做很多事情,比如打包前先删除某个缓存目录的文件,每次打包时自动递增修改 versionCodeversionName ,检查 local.properties 配置文件是否存在已经配置是否正确等等。

3. 修改包的输出路径

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def date = releaseTime()
            //这里只改变 release 包的输出路径
            if (variant.buildType.name.contains('release')) {
                //我们定义包的输出路径为 android_outputs/Android_APK
                //这里可以根据情况定义任意路径
                variant.packageApplicationProvider.get().outputDirectory = new File(project.rootDir.absolutePath + File.separator + "android_outputs"+ File.separator + "Android_APK")
                //包名范例:Android-pro-release-v2.6.6-c266-d202108181428.apk
                def fileName = "Android-${variant.productFlavors[0].name}-${buildType.name}-v" + versionName + "-c" + versionCode + "-d" + date + ".apk"
                output.outputFileName = fileName
            }

            //拓展一下,也可以根据 productFlavors 来做配置
            /*
            if (variant.getName() == "qaRelease") {
                //这里还可以动态修改 productFlavors 里的东西,例如:
                variant.buildConfigField "String", "APP_CHANNEL", '"xiaomi"'
            } else if (variant.getName() == "proRelease") {                

            }
            */
        }
    }
}

def releaseTime() {
    return new Date().format("yyyyMMddHHmm")
}

4. 找到版本冲突的库

当项目越来越大,所使用的第三方库越来越多的时候,最让人头疼的是针对同一个库引入了多个不同的版本,编译的时候导致库冲突直接编译失败,问题找起来也很麻烦。还是利用resolutionStrategy,我们可以快速找到冲突的库以及各版本号,配置如下:

configurations.all {
    resolutionStrategy {
        failOnVersionConflict()
    }
}

下面是一个范例,在我的项目当中,om.android.support:multidex这个库引入了2个不同的版本:1.0.3 和 1.0.2

Conflict(s) found for the following module(s):
  - com.android.support:multidex between versions 1.0.3 and 1.0.2

找到冲突的库及版本后,我们可以用前面的方法,强制指定统一的版本号以解决冲突。

持续更新中......

系列文章

Android Gradle学习(一):Gradle基础入门
Android Gradle学习(二):如何创建Task
Android Gradle学习(三):Task进阶学习
Android Gradle学习(四):Project详解
Android Gradle学习(五):Extension详解
Android Gradle学习(六):NamedDomainObjectContainer详解
Android Gradle学习(七):Gradle构建生命周期
Android Gradle学习(八):统计Task执行时长
Android Gradle学习(九):一些有用的小技巧

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容