gradle 插件开发踩坑记,应用插件时总是报 UnknownPluginException 异常

2023-05-16

问题描述

引用一个本地开发的 gradle 插件时,一直找不到这个插件 ID,报错:

Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin with id xxx found

前言

gradle 插件开发过程中,我们一般会先进行本地部署,通过本地依赖集成进行验证、调试。

其中一个很关键的环节就是,指定插件的 ID, 方便我们在使用插件的 module 中通过 apply plugin: '${}pluginId}' 的方式引入插件,比如我们平时见得比较多的插件 ID 有:com.android.application、com.android.library、java、maven、groovy 等。

如何声明 Gradle 插件 ID

那么这个插件 ID 是怎么指定的呢?

首先给出官方文档 Example: Wiring for a custom plugin

大意如下:

参考文件:src/main/resources/META-INF/gradle-plugins/org.samples.greeting.properties
implementation-class=org.gradle.GreetingPlugin
属性文件名(org.samples.greeting)与插件 ID(org.samples.greeting) 相匹配,放置在 resources 目录下,其中 implementation-class 属性指向插件的实现类(org.gradle.GreetingPlugin)

简单概括下来就是以下几步:

在 src/main 目录下新建resources/META-INF/gradle-plugins目录

目录里面创建一个${pluginId}.properties 文件(${pluginId} 为要指定的插件 ID)

文件内添加一行内容:implementation-class=xxx.xxx.xxx.xxxPlugin(其中 xxx.xxx.xxx.xxxPlugin 指向实际的插件实现类,即实现了Plugin<Project> 接口的类)

插件 ID 的命名

这个插件 ID 怎么命名呢?有些人喜欢用一个简单的单词,有些人喜欢用一个包名,当然这个是不受限制的,参考前面给的常见的 ID,个人觉得只要是一个合法的文件名应该都可以(此处未考究,欢迎大佬给出官方链接)吧,按个人喜好或者公司统一规定来定即可。

问题复现情景

插件写完了,配置也弄好了,开始本地部署与调试了。

正常情况下按照以上步骤来,应该问题不大。

复现背景

但有的时候,相信肯定有很多人和我一样,学习 gradle 插件开发并非从阅读官方文档开始的,要么从网上看到一篇文章就开始着手开发,要么从 GitHub 上找到一份有意思的 gradle 插件的代码,突发奇想,将其 clone 下来改造改造就成了自己的插件了…

问题复现

这么下来,我们就很容易遇到本文提到的这个坑了:应用插件时找不到我们部署好的插件,报错如下:Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin with id xxx found(这里得 xxx 就是 apply plugin 后面给的插件 ID)

复现场景

比如我 clone 一份代码并打开后,显示如下:

没看过文档的我也知道这个 rcplugin 跟 app module 的 build.gradle 中 apply plugin: 'rcplugin' 里的 rcplugin是一一对应的

不假思索的在自己工程里面依次新建:resources/META-INF.gradle-plugins(踩坑点) 目录,新建一个 myplugin.properties 文件,添加一行内容…

在自己工程的 app module 的 build.gradle 中 apply plugin: ‘xxx’

点击 AS 的 Sync Now 后报错:Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin with id xxx found

Why ?Wtf!!!

问题分析

遇到这个问题,你无论怎么比对两个地方的插件 ID 是否匹配,瞪大眼睛,放大 10 倍也找不出问题来。其实这个坑源自一个小小的细节问题,算是 AS 的一个坑吧,也可以说是个人的不细心导致。

要说是 AS 的坑,其实是 AS 的一个小功能:目录合并折叠(姑且这么叫吧)功能

描述:

      AS Project 导航栏视图下,一些常见的目录,如:java、groovy、kotlin、resources 目录下的多级目录(一般包名居多),如果中间某个目录下只有文件夹、没有文件时,AS 会将其用 “.” 号分隔,合并显示,如com/android/library 三级目录显示成com.android.library,上面的META-INF/gradle-plugins显示成META-INF.gradle-plugins。

好处:

这么做自然有其好处,比如包名层级比较多的时候,多级目录显示成一级目录,一次点击就可以展开到包含文件或者包含多个目录的那一层,方便我们快速定位目标层级

坏处:

除了视觉上的误导之外,如果我想在一个多层包名中间新建一个文件,比如在com/android/library 这个目录上右键新建文件,我无法创建 com.android.MyClass 这个文件,常规做法要么去文件夹下新建一个空白文件然后重命名,要么在 library 目录下新建好文件后,使用 AS 的功能键Refactor>Move Class...来重命名操作,着实不方便

解决思路

所以遇到UnknownPluginException这个异常时,按照以下几步仔细检查一下

检查resources/META-INF/gradle-plugins目录 properties 文件名与 apply plugin 引用的插件 ID是否匹配

注意检查一下目录的层级是否正确,比如在本地文件管理器里面打开一下这个目录看看层级,或者用 tree 命令(附菜鸟教程Linux tree命令)试试

或者找一个正确的插件,将其 整个resources 目录拷贝到本项目的src/main目录下,对比看看有什么差异(笔者就是这个方式找到问题所在)

插件 ID 的配置(重复、详细)

这里再重复一下 插件 ID 的配置以加深印象

目录结构:resources\META-INF\gradle-plugins${pluginId}.properties

目录树如下:

└─resources
    └─META-INF
        └─gradle-plugins
               ${pluginId}.properties
注: META-INF 与 gradle-plugins 是两级目录,不是 META-INF.gradle-plugins 目录

示例如下:

看着是不是很奇怪,“两个完全一样的目录”为啥不合并呢?其实前者是两级目录META-INF/gradle-plugins,后者是一级目录META-INF.gradle-plugins,目录树如下:

└─resources
    ├─META-INF
    │  └─gradle-plugins
    │          hooklib.properties  // √ 正确
    └─META-INF.gradle-plugins
            hooklib.properties     // × 错误

————————————————

原文链接:https://blog.csdn.net/lxzh12345/article/details/114531089

关注我获取更多知识或者投稿

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gradle 插件开发踩坑记,应用插件时总是报 UnknownPluginException 异常 的相关文章

  • 两个半天一刷Ubuntu入门指令

    目录 两个半天一刷Ubuntu入门指令 一 Ubuntu初次体验 二 设备驱动 三 Ubuntu用户组及其权限分配 四 压缩解压 五 Linux连接文件 六 vim编辑器 七 Linux下C编程 八 gcc和make及其Makefile的引
  • ENV环境配置及其下载网络组件包问题

    准备工作 Env 工具包含了 RT Thread 源代码开发编译环境和软件包管理系统 从 RT Thread 官网下载 Env 工具 在电脑上装好 git xff0c 软件包管理功能需要 git 的支持 git 的下载地址为https gi
  • 芯片flash保护(解锁)

    报错结果 Error while accessing a target resource The resource is perhaps notavailable 就是无法下载程序 解决办法 1 下载ST LINK Utility 链接 x
  • 2.RTT-点灯大师的修炼

    1 创建工程模板 相信大家通过学习上一篇文章 1 RTT 环境搭建 现在能熟练的创建一个标准模板了 xff0c 如果不会就跳回去学习一下吧 链接 xff1a 1 RTT 环境搭建 嵌入式路上的流浪的博客 CSDN博客 建立好的工程模板编译并
  • 4.RTT-UART-中断接收及轮询发送

    本期博客开始分享RTT的UART xff0c 利用战舰V3的uart2来输入输出一些字符串 UART xff08 Universal Asynchronous Receiver Transmitter xff09 通用异步收发传输器 xff
  • 12.RTT-IIC设备-AHT10温湿度传感器

    本系列博客更新结束啦 xff01 完结啦 xff01 xff01 xff01 撒花 xff01 xff01 xff01 关于RTT的设备和驱动专题更新完毕啦 xff0c 本期是最后一期 一段学习旅途的结束意味着下一段学习冒险的开始 虽然本系
  • RTduino+sht31温湿度传感器

    本次博客使用的是STM32F103C8T6 xff0c 因为该BSP已经对接好RTduino了可以直接上手使用 一 RTduino简介 RTduino是RT Thread实时操作系统的Arduino生态兼容层 xff0c 为RT Threa
  • 一文揭秘字节跳动、华为、京东的薪资职级

    声明 xff1a 本文所有数字均不是官方数据 xff0c 为网络资料收集整理 字节跳动 01 全球员工总数 字节的员工数量目前超过5万人 图片来源 xff1a 字节范 02 岗位职级 字节跳动的职级研发序列一共10级 xff1a 字节跳动创
  • ESP_C3在ubuntu下运行RT-Thread

    1 clone源代码RT Thread git clone git 64 github com RT Thread rt thread git 2 开始搭建ESP IDF环境 进入源码到bsp文件夹下找到ESP32 C3 xff0c 开始配
  • uniapp中使用弹出层

    uniapp中使用弹出层 因为业务的需要 xff0c 需要弹出一个复选框 xff0c 使用uniapp中自带的框架 使用 xff1a 第一步 xff1a 下载下示例项目 xff0c 找到主要的文件夹 第二步 xff1a 将该文件夹放到组件的
  • 手写一个uniapp的步骤条组件

    span class token operator lt span template span class token operator gt span span class token operator lt span view span
  • uniapp中的分页

    数据量过多就会使用分页 第一种 xff1a API span class token comment 和data同级 span span class token function variable function onReachBotto
  • uniapp中生成随机的二维码并进行保存

    需求 xff1a 需要根据用户id的不同生成不同的二维码 xff0c 并进行本地保存 第一步 xff1a 下载插件 这里对于二维码的生成 xff0c 使用的是第三方插件weapp qrcode min js xff0c 主要用到的文件是 d
  • Pc端的基本Echarts

    Pc端的基本Echarts 双环传态图组件 span class token operator lt span template span class token operator gt span span class token oper
  • el-table表格的sortable排序的使用以及出现小数、%排序错乱

    前端实现排序 xff1a 只需要在表头上加上一个sortable属性即可 span class token tag span class token tag span class token punctuation lt span el t
  • 浏览器的回退和导航栏的选中转态不同步,路由在新窗口打开

    问题1 xff1a 浏览器的回退和导航栏的选中状态不能同步的问题 问题 xff1a 用户后退时候 xff0c 左边导航栏显示的还是上一个页面的导航 xff0c 但是路由和页面已经变了 span class token operator lt
  • 左右联动-左侧点击相应的位置,右侧随之滚动

    第一步 xff1a npm下载 npm install better scroll save 第二步 xff1a 局部注册 xff08 当前组件 xff09 span class token keyword import span BScr
  • 杂技-各种css小技巧

    渐变字体 background image webkit linear gradient bottom 379ED7 0FE2EE webkit background clip text webkit text fill color tra
  • 深入理解Kotlin无参构造函数

    Unsafe 创建实例 在java中 创建一个对象 其实主要就是3种方法 通过new 关键字来创建 这种是最常见的 通过反射构造方法来创建对象 这种也不少见 很多框架中都有使用 Unsafe类来创建实例 xff0c 这种情况非常少见 这里先
  • VScode 快捷键

    一 VScode 快捷键 这里主要记录是 VScode开发工具常用的快捷键 xff0c 以便提高工作效率 xff0c 以及今后方便查阅 xff01 xff01 xff01 SHIFT 43 ALT 43 I 在选定的每行末尾插入光标CTRL

随机推荐