向Activity的onCreate方法里注入一个Toast
第三篇修改class文件的时候我们没有具体去修改class文件,后来发现修改class文件的时候还存在一些问题,所以这里再总结一下:
private static void injectClass(String className, String path) {
CtClass c = pool.getCtClass(className)
if (c.isFrozen()) {
c.defrost()
}
/**这里进行操作*/
if(isActivity(activities, c)){
injectActivityLifeCircle(c)
}
c.writeFile(path)
c.detach()
}
private static void injectActivityLifeCircle(CtClass c){
System.out.println("注入Activity文件" + c.getName())
if(c != null){
CtMethod onCreateMethod = c.getDeclaredMethod("onCreate")
String insetAfterStr = "android.widget.Toast.makeText(this,\"我是被插入的Toast代码~!!\",android.widget.Toast.LENGTH_SHORT).show(); " //在方法开头插入代码
try {
onCreateMethod.insertAfter(insetAfterStr)
} catch (Exception e){
e.printStackTrace()
}
System.out.println("注入Toast...................................")
}
}
一开始我是上面这样写的,但是运行的时候就会报错。
后来查资料发现需要android的类库,并且要引入Bundle的包,所以需要在getDeclaredMethod("onCreate")之前加入下面的代码
···
pool.appendClassPath(project.android.bootClasspath[0].toString());
pool.importPackage("android.os.Bundle");
···
然后运行不报错了,但是一直没有插入代码。
千辛万苦,最终才发现,Groovy申明字符串的时候有一个三引号,于是就试了一下把字符串的申明改成了
String insetAfterStr = """ android.widget.Toast.makeText(this,"我是被插入的Toast代码~!!",android.widget.Toast.LENGTH_SHORT).show(); """
于是在三引号的包裹下,终于字节码插桩成功了。
接下来面临的就是业务方面的问题了。