news 2026/4/18 11:54:22

基于Gradle8.0的插件开发

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Gradle8.0的插件开发

01

Gradle8.0插件的使用方式

随着Gradle和Android Gradle Plugin的版本升级,以及Kotlin DSL的加入,Gradle的配置和使用方式发生了很大的变化。插件仓库和依赖仓库的配置从之前的根工程下的build.gradle文件移到了settings.gradle.kts文件中,插件的引入方式也从之前的classpath更改为插件Id。插件的使用也是在子模块中由apply方式变更为id方式。

1、老版本中的配置方式

根工程下的build.gradle配置:

buildscript { repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:4.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10" } } allprojects { repositories { google() mavenCentral() } }

app模块的build.gradle配置:

apply plugin: 'com.android.application'

2、新版本中的配置方式

settings.gradle.kts配置:

pluginManagement { repositories { google() mavenCentral() gradlePluginPortal() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }

根工程下的build.gradle.kts配置:

plugins { id("com.android.application") version "8.1.2" apply false //引入插件 id("org.jetbrains.kotlin.android") version "1.8.10" apply false //引入插件 }

apply false:表示只是将插件引入,并不会自动应用插件到项目中(插件里的任务不会自动执行,只有手动调用里面的任务或者配置使用插件后任务才会执行),可以按需在模块中配置使用

app模块的build.gradle配置:

plugins { id("com.android.application") //使用插件 }

02

Gradle8.0插件的自定义流程

之前使用Groovy、Java 、 手动配置的方式演示了Gradle插件的整个自定义流程《自定义gradle插件》。本文使用java-gradle-plugin 和 Kotlin的方式重新梳理下Gradle插件的自定义流程。

1、新建一个Module模块hui_plugin(选择Kotlin Library)

2、在hui_plugin模块的build.gradle.kts中引入“java-gradle-plugin”插件 和 “org.jetbrains.kotlin.jvm” 插件。“java-gradle-plugin”插件可以大大简化插件的开发流程,这个插件会自动将java-library、gradleApi()引入进来,提供gradlePlugin配置插件id、版本号等信息,取代resources中声明插件类,取代maven发布信息的配置。“org.jetbrains.kotlin.jvm”插件支持使用Kotlin编写插件,取代Groovy和Java

plugins { id("java-gradle-plugin") //会自动引入java-library、gradleApi() id("org.jetbrains.kotlin.jvm") //支持kotlin编写插件 }

3、开始编写自定义的Plugin类

class PageAnalysisPlugin : Plugin<Project> { override fun apply(target: Project) { println("Hello PageAnalysisPlugin") } }

4、在hui_plugin模块的build.gradle.kts中配置插件

gradlePlugin { plugins { create("pagePlugin") { group = "com.znh.plugin" version = "1.0.0" id = "com.znh.plugin.page" //插件的唯一标识,使用插件的时候就是这个id implementationClass = "com.znh.plugin.page.PageAnalysisPlugin" //PageAnalysisPlugin的全类名 取代resources声明 } } }

5、添加maven-publish插件,配置本地仓库地址以便于发布到maven

plugins { id("java-gradle-plugin") //会自动引入java-library、gradleApi() id("org.jetbrains.kotlin.jvm") //支持kotlin编写插件 id("maven-publish") //发布到maven } publishing { repositories { maven { url = uri("../custom_plugin_repo") //本地maven地址 } } }

6、发布到maven仓库

7、生成本地maven仓库,至此,一个Gradle插件的自定义开发和发布就都完成了,相比于老的插件开发方式流程简化了很多

8、插件的使用需要先配置本地maven仓库,在settings.gradle.kts中配置本地仓库地址

pluginManagement { repositories { maven { url = uri("./custom_plugin_repo") } } }

9、在工程根目录下的build.gradle.kts引入插件

plugins { id("com.znh.plugin.page") version "1.0.0" apply false }

10、在app下的build.gradle.kts中使用插件

plugins { id("com.znh.plugin.page") }

11、输出打印结果

03

Transform的替代方案

根据官方文档《Android Gradle 插件 API 更新》可知,Transform在7.2版本中被标记为废弃,在AGP8.0中被移除,但是并没有提供直接替代它的单一API,而是提供了几种场景的解决方案(转换字节码、向应用添加生成的类、基于整个程序分析的转换)。

像方法耗时统计、页面打点统计这类只需要在遍历中直接修改对应的class即可,不涉及到复杂的逻辑,可以使用转换字节码的方案进行实现。转换字节码的实现需要用到Instrumentation API,使用此API,每个类的插桩修改都是独立运行的,可以并行执行,效率较高。

之前基于Transform实现过一个模拟页面打点统计的Demo《ASM和自定义Transform的应用实践》,本文还以模拟页面打点统计为例,结合Instrumentation的transformClassesWith和AsmClassVisitorFactory来实现对Class的插桩修改。对于较复杂的场景后续考虑以路由信息收集为例使用“基于整个程序分析的转换”方案进行实现。

1、在hui_plugin模块的build.gradle.kts中引入android依赖

dependencies { implementation("com.android.tools.build:gradle:8.1.2") }
2、定义一个AsmClassVisitorFactory类,然后实现其createClassVisitor方法和isInstrumentable方法,createClassVisitor方法中对class进行ASM修改操作,isInstrumentable方法定义需要修改的class的过滤条件。PageClassVisitor具体对Class的ASM操作跟之前一样,这里就不粘贴代码了,有兴趣的可以直接查看Demo代码。(ASM的字节码操作可以先用kotlin编写,然后使用AS工具转换成字节码。也可以结合ChatGPT,AI对这种标准化程度较高的功能比较擅长)
abstract class PageClassVisitorFactory : AsmClassVisitorFactory<InstrumentationParameters.None> { override fun createClassVisitor(classContext: ClassContext, nextClassVisitor: ClassVisitor): ClassVisitor { return PageClassVisitor(nextClassVisitor) } override fun isInstrumentable(classData: ClassData): Boolean { return classData.superClasses.contains("android.support.v7.app.AppCompatActivity") || classData.superClasses.contains("androidx.appcompat.app.AppCompatActivity") || classData.superClasses.contains("androidx.activity.ComponentActivity") } }
3、在apply中通过Instrumentation进行遍历修改class
override fun apply(target: Project) { println("Hello PageAnalysisPlugin") val androidComponents = target.extensions.getByType(AndroidComponentsExtension::class.java) androidComponents.onVariants { variant -> variant.instrumentation.transformClassesWith( PageClassVisitorFactory::class.java, InstrumentationScope.ALL ) {} variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES) } }

4、输出打印结果

Page_TAG com.znh.gradle80.plugin.demo I com/znh/gradle80/plugin/demo/MainActivity--->onCreate Page_TAG com.znh.gradle80.plugin.demo I com/znh/gradle80/plugin/demo/FirstActivity--->onCreate Page_TAG com.znh.gradle80.plugin.demo I com/znh/gradle80/plugin/demo/SecondActivity--->onCreate Page_TAG com.znh.gradle80.plugin.demo I com/znh/gradle80/plugin/demo/SecondActivity--->onDestroy Page_TAG com.znh.gradle80.plugin.demo I com/znh/gradle80/plugin/demo/FirstActivity--->onDestroy Page_TAG com.znh.gradle80.plugin.demo I com/znh/gradle80/plugin/demo/MainActivity--->onDestroy

Demo地址:https://github.com/huihuigithub/blog_demo_projects(gradle80-plugin-demo)

参考文档

  1. Android Gradle 插件 API 更新:https://developer.android.google.cn/studio/releases/gradle-plugin-api-updates?hl=zh_cn

  2. 扩展 Android Gradle 插件:https://developer.android.google.cn/studio/build/extend-agp?hl=zh_cn

  3. 开发自定义 Gradle 插件:https://docs.gradle.org/current/userguide/custom_plugins.html

  4. Gradle Plugin 开发插件:https://docs.gradle.org/current/userguide/java_gradle_plugin.html#java_gradle_plugin

  5. 使用 Gradle 插件:https://docs.gradle.org/current/userguide/plugins.html#sec:plugin_markers

  6. Android Gradle 插件版本说明:https://developer.android.google.cn/studio/releases/gradle-plugin?hl=zh-cn#updating-plugin

转自:基于Gradle8.0的插件开发

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 7:56:07

BiliBili-UWP:解锁Windows平台最佳B站观影体验的5大理由

还在为B站网页版在Windows上的体验不佳而烦恼吗&#xff1f;BiliBili-UWP第三方客户端为你带来全新的观影革命&#xff01;这款基于UWP框架开发的应用专为Windows用户打造&#xff0c;提供桌面和平板双模式&#xff0c;让你的B站之旅更加流畅舒适。 【免费下载链接】BiliBili-U…

作者头像 李华
网站建设 2026/4/9 10:58:52

36、如何在系统中查找大文件并生成报告

如何在系统中查找大文件并生成报告 在系统管理中,查找大文件并生成相关报告是一项重要的任务。当文件系统满了,往往是因为一个或多个大文件的存在,这些文件可能是新创建、编译或加载的。下面将详细介绍如何使用 shell 脚本实现查找大文件并生成报告的功能。 1. 准备工作 …

作者头像 李华
网站建设 2026/4/18 7:56:55

40、系统操作与伪随机数生成技术详解

系统操作与伪随机数生成技术详解 1. SSA磁盘识别灯控制 在系统中,我们可以对SSA磁盘识别灯进行控制,有以下几种操作方式: - 关闭所有定义的SSA磁盘识别灯 :不考虑卷组状态,运行 all_defined_pdisks 函数来关闭所有定义的SSA磁盘识别灯。 - 基于卷组状态操作 :当…

作者头像 李华
网站建设 2026/4/18 7:39:25

EmotiVoice语音合成在自动驾驶人机交互中的安全感营造

EmotiVoice语音合成在自动驾驶人机交互中的安全感营造 在一辆高速行驶的L3级自动驾驶汽车中&#xff0c;方向盘自动回正、车速悄然下降——系统刚刚完成了一次紧急避障。此时&#xff0c;车内响起一个熟悉而沉稳的声音&#xff1a;“注意&#xff01;前方有动物穿行&#xff0c…

作者头像 李华
网站建设 2026/4/18 7:39:43

EmotiVoice语音合成多实例并发支持:应对高并发请求

EmotiVoice语音合成多实例并发支持&#xff1a;应对高并发请求 在今天的AI应用浪潮中&#xff0c;语音交互早已不再是“能说话”那么简单。用户期待的是有情绪、有个性、像真人一样的声音体验——尤其是在智能客服、虚拟偶像直播、游戏NPC对话等高频互动场景下&#xff0c;系统…

作者头像 李华
网站建设 2026/4/17 22:31:06

25、磁盘分区监控与主机自动ping脚本指南

磁盘分区监控与主机自动ping脚本指南 在系统管理中,监控磁盘分区状态以及确保主机之间的网络可达性是非常重要的任务。以下将详细介绍如何处理陈旧磁盘分区以及如何创建一个自动ping脚本并实现通知功能。 陈旧磁盘分区处理 查找需同步的逻辑卷 使用grep和awk命令组合在管道…

作者头像 李华