适配 AGP8.5 版本,字节码转换(二)

project.extensions.getByType Extension of type ‘AndroidComponentsExtension‘ does not exist 解决 使用Project.pluginManager.withPlugin("com.android.application")过滤模块,获取到ApplicationPlugin,然后进行transform的注册。 阅读详情

在这里插入图片描述

今日图片
时间:2025.02.14 周五
地点:深大地铁站

1. 转换注册

使用 onVariants 添加 transformClassesWith,不同点注意点(有些可能是对于 java 开发来说,突然转到 kotlin 有点不陌生)

  • AppExtension 变成了 AndroidComponentsExtension
  • registerTransform 变成了 onVariants transformClassesWith
  • ClassVisitor 变成了 AsmClassVisitorFactory 接口实现
  • ClassVisitor 构造方法直接传参数,变成了 parameters 成员实现
import com.android.build.api.instrumentation.InstrumentationScope
import com.android.build.api.variant.AndroidComponentsExtension
import com.android.build.gradle.AppPlugin
import org.gradle.api.Plugin
import org.gradle.api.Project

class Check : Plugin<Project> {
    override fun apply(project: Project) {
        println("自定义 Check 插件运行 ================>")

        //在应用 AppPlugin 插件上注册回调
        project.plugins.withType(AppPlugin::class.java) {
            //获取 AndroidComponentsExtension,类似 AGP7 的
            //def appExtension = project.extensions.getByType(AppExtension)
            val androidComponentsExtension =
                project.extensions.getByType(AndroidComponentsExtension::class.java)
            androidComponentsExtension.onVariants { varients ->
                varients.instrumentation.transformClassesWith(
                    TestAsmClassVisitor::class.java,//指定 asm 操作类
                    InstrumentationScope.ALL//指定操作范围
                ) { params ->//指定操作参数,与之前通过 TestAsmClassVisitor 构造函数传参类似
                    params.processClassName.set("com.example.agp8kotlinplugin.MainActivity")
                    params.oldMethodName.set("sayHello")
                    params.newMethodName.set("sayHelloWorld")
                }
            }
        }
    }
}

2. 转换过滤

实现 AsmClassVisitorFactory接口,并重写重要方法

  • isInstrumentable:指定当前类是否需要转换

作用:主要目的是类过滤,明确那部分的类需要转换处理(实现 isInstrumentable 方法)

不同点是:

  • 实现高度抽象的 AsmClassVisitorFactory
  • 使用范型方式传参数,被抽象类成员 parameters 接收
  • 更加明确哪些类需要转换,实现接口 isInstrumentable
import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.android.build.api.instrumentation.InstrumentationParameters
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.objectweb.asm.ClassVisitor

abstract class TestAsmClassVisitor : AsmClassVisitorFactory<TestAsmClassVisitor.TestParams> {

    override fun createClassVisitor(
        classContext: ClassContext, nextClassVisitor: ClassVisitor
    ): ClassVisitor {
        return ClassMethodVisitor(
            instrumentationContext.apiVersion.get(),
            nextClassVisitor,
            parameters.get().oldMethodName.get(),//parameters 输入的参数
            parameters.get().newMethodName.get(),
        )
    }


    //返回值表示输入的类是否需要转入下一步自定义的 classVisitor 处理
    override fun isInstrumentable(classData: ClassData): Boolean {
        if (classData.className == parameters.get().processClassName.get()) {
            println("找到需要处理的类:=${classData.className}")
            return true
        }
        return false
    }

    //自定义输入或输出参数,对应接口 AsmClassVisitorFactory 的 parameters 成员
    interface TestParams : InstrumentationParameters {

        @get:Input
        val processClassName: Property<String>

        @get:Input
        val oldMethodName: Property<String>

        @get:Input
        val newMethodName: Property<String>
    }
}

3. 转换实现

实现一个简单的需求:你需要自定义映射,混淆指定类里面的特定方法

你看到了我前面的转换输入参数:

明确指定类需要混淆(转换过滤找到指定类)
params.processClassName.set("com.example.agp8kotlinplugin.MainActivity")

明确特定方法混淆的映射(转换实现做混淆替换)
params.oldMethodName.set("sayHello")
params.newMethodName.set("sayHelloWorld")
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor

class ClassMethodVisitor(
    apiVersion: Int,
    cv: ClassVisitor,
    private val oldMethodName: String,
    private val newMethodName: String
) : ClassVisitor(apiVersion, cv) {
    override fun visitMethod(
        access: Int,
        name: String?,
        descriptor: String?,
        signature: String?,
        exceptions: Array<out String>?
    ): MethodVisitor {

        println("当前类包含的方法=${name}")

        if (name == oldMethodName) {
            println("\t找到要处理的方法=${name},修改为=${newMethodName}")
            return super.visitMethod(access, newMethodName, descriptor, signature, exceptions)
        }
        return super.visitMethod(access, name, descriptor, signature, exceptions)
    }
}

运行输出

在这里插入图片描述

实际效果:sayHello 成功修改为映射后的 sayHelloWorld

在这里插入图片描述
在这里插入图片描述

4. 低版本对比

代码上看相比之前的 AGP4+ transform 确实简洁了很多,之前的 transform 方法重写需要关注的地方比较多:

  • transformInput.getJarInputs():需要处理 jar 文件
    • 拿到 jar 遍历读取里面的每个 element
    • 有各种不同类型的 element,还需要过滤 class 文件
    • 再确定当前 class 是否属于处理目标文件
    • 是目标文件,才以字节数组输入到具体 asm 操作转换
    • asm 修改完毕之后还要自己保存,否则下一个 transform 没有输入

  • transformInput.getDirectoryInputs():需要处理目录下的 class 文件
    • 需要遍历目录读取每个 class 文件
    • 再确定当前 class 是否属于处理目标文件
    • 是目标文件,才以字节数组输入到具体 asm 操作转换
    • asm 修改完毕之后还要自己保存,否则下一个 transform 没有输入

如果还是不同清楚 AGP8 之前的 transform,你可以查看之前的文章大概了解:AGP4 Transform 小结

AGP 低版本时候感觉确实麻烦

我觉得升级还是挺有必要的,升级往往带来的是效率的提升和各种优化

对你还可以接触新知识,何乐而不为

实际项目生产环境可能不会这么轻易升级,你应该有自驱力,主动接触新知识

Gradle与AGP版本对应关系全解析:升级迁移避坑指南 在Android工程化开发中,构建工具与插件的版本兼容性是保障项目稳定构建的基石。Gradle作为通用自动化构建系统,负责任务调度与依赖解析,而Android Gradle插件(AGP)则在此之上定义Android特有的编译、打包与签名规则。两者之间存在严格的版本对应关系,一旦Gradle版本低于AGP要求的最低版本,或JDK运行环境不匹配,便会引发构建失败、编译卡死等问题。理解版本矩阵与升级路径,不仅能帮助开发者快速定位错误,也能在引入新特性时降低迁移成本。无论是新建项目还是维护老工程,掌握从Gradle 阅读详情

相关推荐

【疑难排查】Android Build Tools 31.0.0 版本 DX 组件缺失的修复与版本适配解析

本文详细解析了Android Build Tools 31.0.0版本中DX组件缺失导致的'Build Tools 31.0.0 is corrupted'错误,提供了快速重命名D8为DX的临时解决方案,并推荐升级Gradle插件版本等长期适配策略。文章深入探讨了D8与DX的历史演进、性能对比及迁移实践经验,帮助开发者高效解决版本兼容性问题。

weixin_33722405的博客 476

Android 基于Gradle 7.2+,自定义插件示例(实测7.4.2也可以运行)

前几天,找到了之前从官方公众号中,收藏的文章,来简单学习一波Gradle与AGP。 就是这一篇:Gradle 与 AGP 构建 API: 进一步完善您的插件!,文章内部会发现,这是一个小系列,共有3篇文章。

打渔还是晒网 —— stone 5411

从dx到d8:一次Android编译报错,带你理清Build Tools的版本变迁史

本文深入探讨了Android构建工具从dx到d8的技术演进历程,解析了编译报错背后的版本变迁史。通过对比dx与d8的技术原理和性能差异,提供了构建工具版本管理的实战策略和疑难问题排查指南,帮助开发者高效应对Android构建工具链的升级挑战。

weixin_30781775的博客 528

常用的字节码-字符串-进制转换

踏足人生征途,止步眺望云升之际。股市动荡,金融倒闭,世事变幻,灾难频袭,人生难免波折,大多数人必经坎坷,甚至跌宕起伏。此时,何所依?至人生岔路口,择路而行,闭门思过,取笔纸,列举利弊,斟酌其中,最终得出明智抉择。然而,在人生重大决策之际,理智思辨难以决断,此时需考验内心之力,思想之力。

愿Bug与你同在 647

AGP8下TheRouter编译优化实战:从3分12秒到1分45秒

Android Gradle Plugin(AGP)作为Android开发的核心构建工具,其性能直接影响开发效率。随着AGP8废弃Transform API并引入AsmClassVisitorFactory,编译架构发生了重大变革。这种变化虽然带来了增量处理、并行化支持等优势,但也导致部分框架如TheRouter出现编译耗时激增问题。路由框架的编译优化涉及字节码处理、缓存机制和并行计算等技术,在模块化项目中尤为重要。通过实现增量处理、三级缓存策略和并行化改造,可以显著提升构建速度。本文以阿里开源的TheRo

weixin_28837817的博客 334

别再为Android低版本兼容头疼了!手把手教你用AGP 7.0+和Desugaring搞定Java 8新API

本文详细介绍了如何使用AGP 7.0+和Desugaring技术解决Android低版本兼容Java 8新API的问题。通过环境准备、核心配置三步走和高级优化技巧,帮助开发者彻底告别兼容性崩溃,提升应用稳定性。特别适合金融、电商等对日期处理要求高的场景。

weixin_42628688的博客 86

Android Gradle8.0 Transform 废弃如何适配,手撸Arouter插件教你使用

最近公司也在适配项目至Android 14 否则市场不让上架,因此 gradle也必须适配升级了,就先来试试水。目前最新的AGP已经到8.3了,适配AGP8.0也要提上日程了,尤其是一些插件项目,因为8.0删除了transform API,所以需要提前做好适配工作。对于之前未了解过gradle自定义插件的同学可以看下我以前的7.0之前的gradle自定义插件的用法 教你如何一步步实现路由插件。Android 自定义Gradle插件,使用Transform。

Dream It Possible 2664

机器学习---xgboost算法

问题上表现的十分顶尖,本节将较详细的介绍XGBoost的算法原理。成和剪枝分别对应了经验风险最小化和结构风险最小化, XGBoost的决策树生成是结构风险最小。式(1.1)称为经验风险最小化,训练得到的模型复杂度较高。出结果, 是模型的输出结果;等式右边第⼀部分是模型的训练误差,第⼆部分是正则化项,这里。其中,F是假设空间,假设空间是在已知属性和属性可能取值的情况下,对所有可能满足目标的情。最小化,结构风险最小化的模型往往对训练数据以及未知的测试数据都有较好的预测。的正则化项是K棵树的正则化项相加而来的。

weixin_43961909的博客 1万+

前端埋点方案研究及在Android项目中的实践

目前Android项目主要使用友盟移动统计进行用户数据基本分析,友盟APM与腾讯buggly结合进行异常监控,使用优化后的代码埋点框架进行业务埋点。由于友盟统计越来越多的功能开始收费,同时随着项目业务数据分析需求的定制化发展,我们也需要对前端数据采集、监控与分析进行一步步的迭代发展,本地数据预处理优化后的ASM无埋点+优化的代码埋点框架+第三方数据分析平台辅助可以是一种比较全面的选择。

lk007007sclk1的博客 1311

从内外参推导IPM变换方程及代码实现(生成AVM环视拼接图)

最近想实现AVM拼接,看了不少博客和论文,不过比较愚钝,一直没能很好理解原理,尤其是怎么在实现时把下文中Z1和Z2消除的,所以严谨的推导了一下对应的公式,如有不对,水平有限,烦请指出~IPM变换(逆透视变换),顾名思义,即将正常透视效应消除的变换,变换结果为鸟瞰图BEV(俯视图);AVM环视拼接一般是将车身前后左右的四个鱼眼相机拼接成环视图(也是俯视),其使用的单应矩阵将四个相机转到同一个俯视坐标系。

mxdsdo09的博客 4174

CM-GAI:基于连续介质力学与最优传输的数据生成新范式

在数据驱动的工程与科学研究中,如何利用有限的物理数据实现可靠预测是核心挑战。传统方法如深度神经网络,在数据稀缺时往往泛化能力不足且缺乏物理一致性。为解决此问题,一种融合物理原理与数据驱动的新范式应运而生。其核心思想是将数据分布的变化类比为连续介质在广义力驱动下的力学变形过程,通过最优传输理论为分布变换提供最优路径的度量。这种方法将物理规律(如质量守恒、运动方程)作为硬约束嵌入模型,确保了生成过程的物理可解释性。物理信息神经网络(PINNs)则被用作高效求解器,处理高维特征空间中的复杂控制方程。在工程实践中,

weixin_30607029的博客 608

AGP 升级,适配 8.5 版本(一)

本次升级是从之前的 AGP7+ 升级到 AGP8+

Primer5 2839

用Bus Hound和MIDIOX抓包分析USB MIDI数据流:从硬件接口到软件解析的完整实战

本文详细介绍了如何使用Bus Hound和MIDIOX工具抓包分析USB MIDI数据流,从硬件接口到软件解析的完整实战过程。通过解析MIDI协议、捕获Note On/Off事件、控制变更消息等实例,帮助开发者深入理解音乐数字接口的底层通信机制,并提供了常见问题的解决方案和调试技巧。

weixin_42692935的博客 406

Arouter适配AGP 7.3.0版本

如何调试arouter 源码 arouter的代码 主要分为 3个部分,一个是基础的arouter-api包, 然后是注解处理器arouter-compile包 最后是arouter-register 这个包, 简单概述一下 这3个模块的具体作用吧arouter-api:99%的人使用arouter代码 都是直接用这个包下面的api,大部分用下注解就可以了arouter-compiler:这里是注...

Android技术之家 2031

[系统安全] 一.什么是逆向分析、逆向分析基础及经典扫雷游戏逆向

娜璋AI安全之家于2020年8月18日开通,将专注于Python和安全技术,主要分享Web渗透、系统安全、CVE复现、威胁情报分析、人工智能、大数据分析、恶意代码检测等文章。真心想把自己近十年的所学所做所感分享出来,与大家一起进步。 系统安全系列作者将深入研究恶意样本分析、逆向分析、攻防实战等,通过在线笔记和实践操作的形式分享与博友们学习,希望能与您一起进步。第一篇文章先带领大家学习什么是逆向分析,然后详细讲解逆向分析的典型应用,接着通过OllyDbg工具逆向分析经典的游戏扫雷,再通过Cheat Engin

杨秀璋的专栏 2万+

[系统安全] 四十七.恶意软件分析 (3)动态分析经典沙箱Cape的安装和基础用法详解

系统安全将更好地帮助初学者了解病毒逆向分析和系统安全。前文详细介绍恶意代码静态分析经典工具Capa的基础用法,以及批量提取静态特征和ATT&CK技战术,主要是从提取的静态特征Json文件中提取关键特征。这篇文章将详细讲解动态分析沙箱Cape,其是一个开源的自动恶意软件分析系统,通过自动运行和分析恶意软件,全面分析和提取恶意软件的关键特征。本文先介绍Cape沙箱的安装和基础用法,后续随着深入再分享。基础性文章,希望对您有帮助!

杨秀璋的专栏 6739

Android开发必备:AGP是Android构建的核心引擎

摘要:Android Gradle插件(AGP)是Android项目构建的核心组件,主要负责处理Android特有的构建逻辑。其核心功能包括:管理Android专属构建流程(编译、资源处理、打包签名);提供项目配置入口;支持构建变体;优化APK/AAB体积与性能;处理依赖冲突;深度集成开发工具链;适配新版Android系统特性。AGP作为Gradle构建工具与Android开发需求之间的桥梁,自动化了复杂构建流程,让开发者专注于业务逻辑开发。正确选择与Gradle版本匹配的AGP版本对项目稳定性至关重要。

上市公司前技术负责人,20 年软硬件深耕 + 百人研发团队管理经验,名校理工科背景加持。从技术攻坚到团队掌舵,沉淀海量项目实战与管理心得,专注分享软硬件干货、疑难问题解决方案,既是靠谱知识传播者,也盼链接优质项目共成长。 1026

在 SAP 系统中,成本中心(Cost Center)是成本核算与费用管控的基础组织单元,其设计质量直接决定了后续成本归集、分摊、分析及责任考核的准确性

SAP系统成本中心设计核心要点:1. 设计原则包括责任可控、业务同质、核算颗粒度适配、组织对齐及稳定性平衡;2. 划分维度主要有部门、功能、地域、项目和资产5类,可组合使用;3. 需避免颗粒度过细、跨责任主体归集等常见误区;4. 建议采用"明确目标-梳理业务-设计编码"三步法,建立科学的成本中心体系。合理的成本中心设计能精准归集费用、明确责任主体,为成本分析和管控奠定基础。

金牌架构师 1443

Android Studio Gradle 8.0 适配指南

详解Android Studio中Gradle 8.0的适配方法。首先,我需要从提供的搜索结果中找到相关的信息,尤其是关于Gradle 8.0适配的内容。记得每个步骤都要引用对应的网页来源。首先,搜索结果里的网页1提到了Gradle 8.0废弃了Transform API,转而使用AsmClassVisitorFactory。这点很重要,因为Transform API的移除会影响很多现有的插件。

缘来的精彩的博客 2765

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

android脱糖

`Android 5`、`Adnroid 6`系统原生只支持到`Java 7`,`Android 7`原生仅支持部分`Java 8`特性(比如Lambda表达式),到了`Android 8`则完整支持`Java 8`了。我们写Android项目时,对于兼容性,一般来说指定`minSdk`就可以了,比如`minSdk`设置为21,对应为`Android 5`,也就是说这个项目需要兼容的最低版本是`Android 5`,假设我们把`targetCompatibility`和`jvmTarget`设置为11,那生

Android菜鸟的专栏 2211

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【Android】关于D8/R8那些事:Desugaring脱糖、APK包体积优化等

Desugaring脱糖? 不同的Android版本支持的Jvm版本不同,当使用当前Abndroid版本不支持的高版本jdk语法时,需要在编译期转换为其支持的低版本jdk语法,这个过程成为desugaring脱糖。 我们分别在Android R (API 30) 和 Android M (API 23)上分别调用Java8新引入的时间API tv_month.text = LocalDate.now().month.name AndroidR可以正常运行,但是AndroidM出现了NoClassDe.

移动端开发干货分享 9090

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

安卓构建工具D8和R8的区别

D8 是 Android 现代编译流程的基石,保证了高效的基础编译;而 R8 则是在此基础上,为应用发布版本准备的“增强包”,旨在打造更小、更快、更安全的 APK。

qq_40323742的博客 656

别再为Android低版本兼容头疼了!手把手教你用D8/R8的Desugaring搞定Java 8新API

本文详细介绍了如何利用D8/R8的脱糖(Desugaring)技术解决Android低版本兼容性问题,特别是Java 8新API在低版本设备上的崩溃问题。通过配置Gradle插件、启用核心库脱糖、验证效果及处理多模块项目,开发者可以轻松实现全版本兼容。文章还提供了高级技巧与避坑指南,帮助优化性能和迁移遗留代码。

weixin_30256901的博客 372

刚学会Transform,你告诉我就要被移除了

已经2022年了,作为一名Android工程师,我相信大家都知道Transform是什么,如果有人不知道,也没关系,因为Transform已经快过时了,按照惯例,这里我还是要介绍一下TransformAGP包含了一个TransformAPI,它允许第三方插件在编译后的class文件转换为dex文件之前做处理操作.而使用TransformAPI,我们完全可以不用去关注相关task的生成与执行流程,我们可以只聚焦在如何对输入的class文件进行处理工作时机处理对象Transform链。.........

bugyinyin的博客 1969

Android Studio Narwhal:AGP 8.7+ 与 Gradle 8.9 构建范式重构指南

Android Studio Narwhal(2025)标志着 Android 构建体系从脚本驱动到模型驱动的根本性演进。其核心在于 AGP 8.7+ 作为语义中枢、Gradle 8.9+ 作为执行底座的主从协同架构,彻底摒弃 Groovy 脚本与废弃 API,强制采用 Kotlin DSL 声明式配置。这一转向不仅消除了‘deprecated gradle features’等兼容性警告,更通过内存中 Project Model 实现编译前静态分析、实时依赖推演与增量构建优化,显著提升大型项目构建与 ID

daxi1047的博客 491
上一篇: AGP 升级,适配 8.5 版本(一)
下一篇: Android:启动本地 http-server 加载 h5 游戏
Primer@.com
博客等级 码龄9年 524粉丝 292原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值