本插件可实现AGP7.4+和AGP8下ARouter框架自动化插桩,使用方法和com.alibaba:arouter-register
完全一致,无缝替换;
最新版本1.0.2, 修复和优化
为了不影响篇幅,请到最底部查阅详细内容;
插件发布在 ArouterPlugin ,点开即可查阅最全面的插件导入方式;
Koltin
Using the plugins DSL:
plugins {
id("io.github.JailedBird.ARouterPlugin") version "1.0.2"
}
Using legacy plugin application:
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath("io.github.JailedBird:arouter-gradle-plugin:1.0.2")
}
}
apply(plugin = "io.github.JailedBird.ARouterPlugin")
Grovvy
Using the plugins DSL:
plugins {
id "io.github.JailedBird.ARouterPlugin" version "1.0.2"
}
Using legacy plugin application:
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath "io.github.JailedBird:arouter-gradle-plugin:1.0.2"
}
}
apply plugin: "io.github.JailedBird.ARouterPlugin"
遍历注解处理器生成的路由信息,然后在loadRouterMap函数中插桩
override fun visitInsn(opcode: Int) {
// generate code before return
if (opcode in Opcodes.IRETURN..Opcodes.RETURN) {
targetList?.forEach { scanSetting ->
scanSetting.classList.forEach { name ->
val className = name.replace("/", ".")
mv.visitLdcInsn(className)// 类名
mv.visitMethodInsn(
Opcodes.INVOKESTATIC,
ScanSetting.GENERATE_TO_CLASS_NAME,
ScanSetting.REGISTER_METHOD_NAME,
"(Ljava/lang/String;)V",
false
)
}
}
}
super.visitInsn(opcode)
}
插桩后字节码如下:
.method public static loadRouterMap()V
.registers 1
.line 63
const/4 v0, 0x0
sput-boolean v0, Lcom/alibaba/android/arouter/core/LogisticsCenter;->registerByPlugin:Z
.line 68
const-string v0, "com.alibaba.android.arouter.routes.ARouter$$Root$$app"
invoke-static {v0}, Lcom/alibaba/android/arouter/core/LogisticsCenter;->register(Ljava/lang/String;)V
const-string v0, "com.alibaba.android.arouter.routes.ARouter$$Root$$arouterapi"
invoke-static {v0}, Lcom/alibaba/android/arouter/core/LogisticsCenter;->register(Ljava/lang/String;)V
const-string v0, "com.alibaba.android.arouter.routes.ARouter$$Providers$$app"
invoke-static {v0}, Lcom/alibaba/android/arouter/core/LogisticsCenter;->register(Ljava/lang/String;)V
const-string v0, "com.alibaba.android.arouter.routes.ARouter$$Providers$$arouterapi"
invoke-static {v0}, Lcom/alibaba/android/arouter/core/LogisticsCenter;->register(Ljava/lang/String;)V
return-void
.end method
1、 解决issue7 debug阶段编译慢的问题;宿主模块启用如下配置,可避免在debug的变体下进行插桩,此时会通过Arouter原生遍历dex寻找路由文件,首次启动慢,之后会保存在SP中,速度应该还可以接受;缺点是路由表表更,需要清除应用数据才能生效;默认关闭,推荐开启(毕竟大项目编译非常慢);
arouter_config {
disableTransformWhenDebugBuild = true
}
2、 字节码插桩从ASM5升级到ASM7,解决 issue6 其实我暂时没弄懂这个原理,只是改了插桩API的这个ASM版本参数;
3、 重要:demo添加混淆规则! 分支 bugfix/agp8.2.2_runtime_error 实验发现AGP 8.2.2启用混淆minify后,貌似 会把 TypeWrapper的匿名内部类从泛型ParameterizedType混淆为Class,导致类型转换报错;
public class TypeWrapper<T> {
protected final Type type;
protected TypeWrapper() {
Type superClass = getClass().getGenericSuperclass();
type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public Type getType() {
return type;
}
}
导致对象注入时候,类型解析抛出异常;
if(serializationService != null) {
val res = substitute.intent?.extras?.getString("list")
if(!res.isNullOrEmpty()) {
val typeWrapper = object : TypeWrapper<MutableList<String>>(){}
serializationService?.parseObject<MutableList<String>>(res, typeWrapper.type)?.let{
substitute.list = it
}
}
}
添加如下混淆即可:【没出现问题,不加也行】
# 避免继承自TypeWrapper的匿名内部类(获取泛型T对应的Type)被混淆 导致Type获取失败
# Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
# at com.alibaba.android.arouter.facade.model.TypeWrapper.<init>(TypeWrapper.java:19)
# 这种情况下 就是匿名内部类被混淆导致 getClass().getGenericSuperclass() 从ParameterizedType变为Class从而导致Type类型转换异常
-keep class ** extends com.alibaba.android.arouter.facade.model.TypeWrapper { *; }
相关文档见issue1,如果对您有帮助,请点亮star支持作者😘