Android基于gradle task检查各个module之间资源文件冲突情况

做组件化开发的时候,我们经常会遇到各个不同的module之间资源文件冲突的问题,运行也不报错,但是会出现覆盖的问题,导致运行之后发送错误的效果。

所以我们需要利用一个gradlke 脚本task,来自动化检查资源文件冲突。

定义一个android gradle脚本,检查各个module之间资源文件冲突(命令重复)的task。

Android基于gradle task检查各个module之间资源文件冲突情况 点击查看原文

Android不同module资源布局文件重名被覆盖

下面是一个完整的 Gradle 脚本示例,用于检查不同模块之间的资源文件冲突。这个任务将遍历所有子模块的资源文件,并在发现同名文件时输出冲突信息。脚本中包含了详细的注释,便于理解每个步骤。

1. 根 build.gradle 文件

在项目的根目录下的 build.gradle 文件中定义任务:

groovy复制代码// 根 build.gradle 文件
buildscript {repositories {google()mavenCentral()}dependencies {classpath 'com.android.tools.build:gradle:8.1.1' // 请根据需要调整版本}
}allprojects {repositories {google()mavenCentral()}
}task checkResourceConflicts {doLast {def resourceFiles = [:] // 存储资源文件,键是文件名,值是包含文件路径和模块名的 Map// 遍历所有子模块subprojects { subproject ->// 检查子模块是否有 Android 配置if (subproject.hasProperty('android')) {subproject.android.sourceSets.each { sourceSet ->sourceSet.res.srcDirs.each { resDir ->if (resDir.exists()) {println("Scanning resources in module: ${subproject.name}, path: ${resDir.absolutePath}")// 遍历资源目录中的文件resDir.eachFileRecurse { file ->if (file.isFile() && file.name.endsWith(".xml")) {def fileName = file.namedef moduleName = subproject.name // 当前模块名// 检查文件名是否已存在if (resourceFiles.containsKey(fileName)) {def existingFileInfo = resourceFiles[fileName]if (existingFileInfo.moduleName != moduleName) {// 如果文件名来自不同模块,报告冲突println "Resource conflict detected: ${fileName} exists in both ${existingFileInfo.moduleName} (${existingFileInfo.filePath}) and ${moduleName} (${file.absolutePath})"}} else {// 存储文件路径及模块名resourceFiles[fileName] = [filePath: file.absolutePath, moduleName: moduleName]}}}} else {println("No resources found in: ${resDir.absolutePath}")}}}} else {println("Skipping module: ${subproject.name} (no Android configuration)")}}println("Resource conflict check completed.")}
}// 在构建之前执行检查任务
gradle.projectsEvaluated {tasks.named("preBuild").configure {dependsOn(checkResourceConflicts)}
}

2. 代码说明

  • 任务 checkResourceConflicts
    • 遍历所有子模块,检查每个模块的资源文件。
    • 使用 subprojects 来遍历每个子模块。
    • 检查每个模块是否包含 android 配置。
    • 如果存在资源文件,逐一检查是否有同名文件。
    • 如果检测到同名文件,输出冲突信息,包含模块名和文件路径。
  • preBuild 任务的依赖
    • 在所有项目评估完成后,将 checkResourceConflicts 任务与 preBuild 任务关联,这样每次构建都会执行检查。

3. 使用步骤

  1. 在项目根目录的 build.gradle 文件中添加以上代码

  2. 确保 settings.gradle 文件中包含所有子模块,例如:

    groovy复制代码
    include ':app', ':module1', ':module2'
    
  3. 运行构建命令

    bash复制代码
    ./gradlew assembleDebug
    

    该命令将触发资源冲突检查,并在控制台打印出任何资源文件冲突的信息。

4. 输出效果

当执行构建命令后,控制台将输出类似于以下的内容:

bash复制代码Scanning resources in module: module1, path: /path/to/project/module1/src/main/res
Scanning resources in module: module2, path: /path/to/project/module2/src/main/res
Resource conflict detected: string_name.xml exists in both module1 (/path/to/project/module1/src/main/res/values/string_name.xml) and module2 (/path/to/project/module2/src/main/res/values/string_name.xml)
Resource conflict check completed.

这样就完成了一个有效的资源文件冲突检查任务。你可以根据需要进一步调整和优化该脚本。

项目根目录gradle.build完整代码

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {id 'com.android.application' version '8.6.0' apply false//8.6.0  '7.1.0id 'com.android.library' version '8.6.0' apply false//8.6.0   '7.1.0id 'maven-publish' apply true// 引入 maven 插件//引入kotlin 插件id 'org.jetbrains.kotlin.android' version '1.9.0' apply false
}// 根 build.gradle
apply from: 'versions.gradle'allprojects {// 在这里共享版本号给所有子项目ext {kotlinVersion = kotlinVersionappCompatVersion = appCompatVersioncoroutinesVersion = coroutinesVersion}
}task checkResourceConflicts {doLast {def resourceFiles = [:] // 存储资源文件,键是文件名,值是包含文件路径和模块名的 Map// 遍历所有子模块subprojects { subproject ->// 检查子模块是否有 Android 配置if (subproject.hasProperty('android')) {subproject.android.sourceSets.each { sourceSet ->sourceSet.res.srcDirs.each { resDir ->if (resDir.exists()) {println("Scanning resources in [module]: [${subproject.name}], path: ${resDir.absolutePath}")// 遍历资源目录中的文件resDir.eachFileRecurse { file ->if (file.isFile() && file.name.endsWith(".xml")) {def fileName = file.namedef moduleName = subproject.name // 当前模块名// 检查文件名是否已存在if (resourceFiles.containsKey(fileName)) {def existingFileInfo = resourceFiles[fileName]if (existingFileInfo.moduleName != moduleName) {// 如果文件名来自不同模块,报告冲突println "Resource conflict detected: ${fileName} exists in both ${existingFileInfo.moduleName} (${existingFileInfo.filePath}) and ${moduleName} (${file.absolutePath})"}} else {// 存储文件路径及模块名resourceFiles[fileName] = [filePath: file.absolutePath, moduleName: moduleName]}}}} else {//  println("No resources found in: ${resDir.absolutePath}")}}}} else {println("Skipping module: ${subproject.name} (no Android configuration)")}}println("Resource conflict check completed.")}
}// 在每个子模块的 preBuild 任务上执行检查
subprojects { subproject ->if (subproject.hasProperty('android')) {subproject.tasks.named("preBuild").configure {dependsOn(checkResourceConflicts)}}
}

在项目根目录gradle.build文件中运行task:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

运行结果如图所示:

> Task :checkResourceConflicts
Scanning resources in [module]: [app], path: D:\Projects\Android\widgets\app\src\aliyun\res
Scanning resources in [module]: [app], path: D:\Projects\Android\widgets\app\src\main\res
Scanning resources in [module]: [app], path: D:\Projects\Android\widgets\app\src\tuya\res
Scanning resources in [module]: [app], path: D:\Projects\Android\widgets\app\src\xiaomi\res
Scanning resources in [module]: [kotlinDemo], path: D:\Projects\Android\widgets\kotlinDemo\src\main\res
Resource conflict detected: activity_main.xml exists in both app (D:\Projects\Android\widgets\app\src\main\res\layout\activity_main.xml) and kotlinDemo (D:\Projects\Android\widgets\kotlinDemo\src\main\res\layout\activity_main.xml)
Resource conflict detected: strings.xml exists in both app (D:\Projects\Android\widgets\app\src\aliyun\res\values\strings.xml) and kotlinDemo (D:\Projects\Android\widgets\kotlinDemo\src\main\res\values\strings.xml)
Scanning resources in [module]: [widgets], path: D:\Projects\Android\widgets\widgets\src\main\res
Resource conflict detected: strings.xml exists in both app (D:\Projects\Android\widgets\app\src\aliyun\res\values\strings.xml) and widgets (D:\Projects\Android\widgets\widgets\src\main\res\values\strings.xml)
Resource conflict check completed.Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.For more on this, please refer to https://docs.gradle.org/8.10.2/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

项目task运行结果如图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/55133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

腾讯云-云直播

云直播(Cloud Streaming Services)为您提供极速、稳定、专业的直播云端处理服务,根据业务中不同直播场景的需求,云直播提供标准直播、快直播、慢直播和云导播台服务,分别针对大规模实时观看、高并发推流录制及超低延时…

Jenkins配置流水线任务-实践操作(Pipeline-script)

Jenkins配置流水线任务-实践操作(Pipeline-script) 1、新增jenkins 任务,选择流水线 2、参数化 3、流水线配置 pipeline {agent anystages {stage(aoePlugin_mysql) {steps {echo "xxx,数据库:Mysql"echo "${HOST},${USER_NAME}"b…

AGI|如何构建一个RAG应用?入门新手攻略!

目录 一、概述 二、过程概述 三、如何优化提问? 四、路由和高级查询 五、丰富索引结构 六、重排序上下文 七、总结 一、概述 Retrieval Augmented Generation RAG 检索增强的内容生成。 从字面上来看检索只是一种手段途径,在人工智能领域中存在多种…

leetcode计数排序

计数排序(counting sort)通过统计元素数量来实现排序,通常应用于整数数组。 给定一个长度为 的数组 nums ,其中的元素都是“非负整数” def counting_sort(nums: list[int]):"""计数排序"""# 完整实…

从调用NCCL到深入NCCL源码

本小白目前研究GPU多卡互连的方案,主要参考NCCL和RCCL进行学习,如有错误,请及时指正! 内容还在整理中,近期不断更新!! 背景介绍 在大模型高性能计算时会需要用到多卡(GPU&#xf…

三勾点餐|后台页面更新

项目介绍 三勾点餐系统基于thinkphp8element-plusuniapp打造的面向开发的小程序商城,方便二次开发或直接使用,可发布到多端,包括微信小程序、微信公众号、QQ小程序、支付宝小程序、字节跳动小程序、百度小程序、android端、ios端。 功能说明…

从头开始的可视化数据 matplotlib:初学者努力绘制数据图

从头开始学习使用 matplotlib 可视化数据,对于初学者来说,可能会有些挑战,但 matplotlib 的核心理念非常清晰:绘制图表需要了解如何设置图形、坐标轴以及如何用数据填充它们。我们可以通过一些简单的例子来逐步介绍基本步骤。 1. …

代码审计笔记-PHP

PHP 1.php的弱类型 PHP 的“弱类型”是指在这门编程语言中,变量的类型在赋值时会被自动推断,而不是在变量声明时显式地指定类型。这意味着在 PHP 中,您可以将不同类型的值赋给同一个变量,而不需要进行类型转换或重新声明变量。 举…

基于Opencv中的DNN模块实现图像/视频的风格迁移

一、DNN模块的介绍 1、简介 OpenCV中的DNN(Deep Neural Network)模块是一个功能强大的组件,它支持深度学习网络模型的加载和推理。虽然DNN模块不提供模型的训练功能,但它可以与主流的深度学习框架(如TensorFlow、Caf…

并行 parallel broadcast partition pruning 分区裁剪 optimizer_dynamic_sampling=7

insert into abc 没有PDML所以不是全部并行 只有select 的情况 全部并行,没有 px send broadcast ,所以rows没从103M变成103*8M select *from A,B where A.Pkey B.Pkey and A.Pkey XX A B表都会进行分区裁剪 ----并行为什么更…

Linux操作系统——外存的管理(实验报告)

实验 Linux系统外存管理 一、实验目的 熟练Linux系统外存管理的方法与命令。 二、实验环境 硬件:PC电脑一台,网络正常。 配置:win10系统,内存大于8G 硬盘500G及以上。 软件:VMware、Ubuntu16.04。 三、实验内容 …

pymobiledevice3 xonsh-afc shell使用介绍

1、进入xonsh-afc shell: pymobiledevice3 apps afc bundle_id 2、进入shell后默认的目录是:[com.apple.mobile.house_arrest:/]$,这个目录是指定bundle_id的沙盒目录。 3、沙盒目录中如果包含带有空格的文件夹,直接使用cd App…

《CUDA编程》8.共享内存的合理使用

共享内存是 一种可被程序员直接操控的缓存,主要作用有两个: ①减少核函数中对全局内存的访 问次数,实现高效的线程块内部的通信 ②提高全局内存访问的合并度 将通过两个具体的例子阐明共享内存的合理使用,一个数组归约的例子和讨矩…

Git上传命令汇总

进入企业,每日需要上传执行用例记录到gitlab平台上,本文记录了常用git上传命令, 并用github演示。 1、本地建立分支,克隆远程仓库 在gitlab中,每个人需要创建自己的分支,一般以自己的名字命名,…

三子棋(C 语言)

目录 一、游戏设计的整体思路二、各个步骤的代码实现1. 菜单及循环选择的实现2. 棋盘的初始化和显示3. 轮流下棋及结果判断实现4. 结果判断实现 三、所有代码四、总结 一、游戏设计的整体思路 (1)提供一个菜单让玩家选择人机对战、玩家对战或者退出游戏…

第二十七篇:传输层讲解,TCP系列一

一、传输层的功能 ① 分割与重组数据 传输层也要做数据分割,所以必然也需要做数据重组。 ② 按端口号寻址 IP只能定位数据哪台主机,无法判断数据报文应该交给哪个应用,传输层给每个应用都设置了一个编号,这个编号就是端口&…

Midjourney官宣网页版免费用!前谷歌大佬祭出AI生图2.0,全网惊艳实测

Midjourney一度稳居AI生图的第一梯队,甚至是很多人心中的Top1。但是Ideogram 2.0的发布,抢夺了Midjourney的荣光,不仅一举拉高了图像生成质量,还打起了价格战。 曾经在AI图像生成领域无可匹敌的领导者Midjourney,终于…

3分钟学会下载 blender

1. blender简介 Blender是一款开源的3D创作套件,它由Blender Foundation维护,并得到了全球志愿者和专业开发者的支持。Blender广泛应用于3D模型的制作、动画、渲染、视频编辑、游戏创建、模拟、 composting以及3D打印等多个领域。 功能特点&#xff1a…

欧盟通过《网络弹性法案》保障联网产品安全

欧盟理事会通过了《网络弹性法案》(CRA),这是一项新法律,旨在使含有数字组件的消费产品更加安全使用。 CRA要求 CRA 概述了欧盟范围内针对数字产品的网络安全标准,即直接或间接连接到其他设备或网络的产品。 此类别…

Qt-QDockWidget浮动窗口相关操作(49)

目录 描述 使用 描述 在 Qt 中,浮动窗⼝也称之为铆接部件。浮动窗⼝是通过 QDockWidget类 来实现浮动的功能。浮动窗口⼀般是位于核心部件的周围,可以有多个。 使用 创建我们可以参考下面的语法格式 使用起来也很简单,不过只能创建一个 Q…