Android 在运行时替换方法调用

4
我正在开发一款带有第三方库的Android应用程序。我想要替换库中的方法调用。请注意,我无法获取库的源代码,因此必须在运行时进行更改。
例如,假设库中的Foo类中有一个doA()方法。
class Foo {
    doA() {
        //method body
    }
    ...
}

我想替换doA()方法的内容为我的代码。我进行了一些探索,并发现以下stackoverflow线程:Replacing a method call in a class at runtime。该线程告诉我可以尝试使用一个称为javassist的字节码操作库。我发现有一个Android版本的库在这里:https://github.com/crimsonwoods/javassist-android。我导入了该库并编写了以下代码:

try {
    final ClassPool cp = ClassPool.getDefault(getApplicationContext());
    CtClass cc = cp.get("Foo");
    CtMethod method = cc.getMethod("doA","()V");
    method.setBody("{ java.lang.System#out.println(\"doA() is called.\");}");
    cc.writeFile();     //where the exception was raised        
} catch (Exception e) {
    e.printStackTrace();
}

但是在执行cc.writeFile()时,我遇到了一个异常。它是"FileNotFoundException: ./Foo.class: open failed: ENOENT (No such file or directory)"。我不知道如何解决这个问题。


不是每个 Android SDK 版本都适用于所有类,这在某些设备上可能有效,在某些设备上则会产生异常。 - Lena Bru
为什么不在运行时使用布尔变量? - Illegal Argument
没有源代码并不等于必须在运行时进行更改。如果可能的话,最好静态修改库,因为动态代码修改不仅更加复杂,而且对病毒扫描器来说也很可疑。 - Antimony
好观点,Antimony。但是我想在运行时编辑它,这样下次库升级时就不必再次进行操作了。如果静态地更改字节码,当库升级时可能还需要再次操作。 - user3598016
1个回答

1

Vaclav,感谢你的建议。我按照示例进行了操作,但是发现另一个问题。我的类非常复杂。仪器化在第56行失败,这是调用DexFile.addClass()的地方。我进行了调试,它深入到我不理解的javassist代码中。我猜测当前的javassist实现无法处理如此复杂的类。 - user3598016

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接