123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- package com.gradle.ares
- import org.objectweb.asm.ClassVisitor
- import org.objectweb.asm.FieldVisitor
- import org.objectweb.asm.Label
- import org.objectweb.asm.MethodVisitor
- import org.objectweb.asm.Opcodes
- import org.objectweb.asm.commons.GeneratorAdapter
- /**
- * Created by Glen on 2017/2/8.
- */
- public class MethodLifeCycleVisitor extends MethodBaseVisitor {
- public final static String[] SuperClass = [
- "android/app/Activity",
- "android/support/v4/app/FragmentActivity",
- "android/support/v7/app/AppCompatActivity",
- "android/support/v4/app/Fragment",
- "android/support/v4/app/ListFragment",
- "android/support/v4/app/DialogFragment",
- "android/app/Fragment",
- "android/app/ListFragment",
- "android/app/DialogFragment"
- ] as String[]
- public final static MethodModel[] Modify = [
- new MethodModel("onCreate", "(Landroid/os/Bundle;)V", 1),
- new MethodModel("onResume", "()V", 0),
- new MethodModel("onPause", "()V", 0),
- new MethodModel("onDestroy", "()V", 0),
- new MethodModel("onSaveInstanceState", "(Landroid/os/Bundle;)V", 1),
- new MethodModel("onRestoreInstanceState", "(Landroid/os/Bundle;)V", 1),
- new MethodModel("setUserVisibleHint", "(Z)V", 1),
- new MethodModel("onHiddenChanged", "(Z)V", 1)
- ] as MethodModel[]
- public
- static MethodModel getAgent(int access, String className, String superName, String name, String desc) {
- for (MethodModel item : Modify) {
- if (item.name.equals(name) && item.desc.equals(desc)) {
- item.access = access
- item.className = className
- item.superName = superName
- return item
- }
- }
- return null
- }
- public
- static void addMethods(Set<MethodModel> agentSet, String className, String superName, ClassVisitor cv) {
- addLifeCycleFieldMethod(className, cv)
- for (MethodModel agent : Modify) {
- if (!agentSet.contains(agent)) {
- //method
- MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, agent.name, agent.desc, null, null)
- GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ASM5, mv, Opcodes.ACC_PUBLIC, agent.name, agent.desc)
- adapter.visitCode()
- adapter.loadThis()
- adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, AresValue.GetLifeMethod, "()L" + AresValue.LifeClass + ";", false)
- for (int i = 0; i < agent.count; i++) adapter.loadArg(i)
- adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, AresValue.LifeClass, agent.name, agent.desc, false)
- adapter.loadThis()
- for (int i = 0; i < agent.count; i++) adapter.loadArg(i)
- adapter.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, agent.name, agent.desc, false)
- adapter.visitInsn(Opcodes.RETURN)
- adapter.visitMaxs(0, 0)
- adapter.visitEnd()
- }
- }
- }
- /**
- * 注入代理字段及初始化方法
- * @param cv
- */
- private static void addLifeCycleFieldMethod(String className, ClassVisitor cv) {
- //desc
- String fieldName = "\$lifeCycleAresDelegate"
- String fieldDesc = "L" + AresValue.LifeClass + ";"
- //field
- FieldVisitor fv = cv.visitField(Opcodes.ACC_PUBLIC, fieldName, fieldDesc, null, null)
- fv.visitEnd()
- //method
- MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, AresValue.GetLifeMethod, "()" + fieldDesc, null, null)
- mv.visitCode()
- mv.visitVarInsn(Opcodes.ALOAD, 0)
- mv.visitFieldInsn(Opcodes.GETFIELD, className, fieldName, fieldDesc)
- Label label = new Label()
- mv.visitJumpInsn(Opcodes.IFNONNULL, label)
- mv.visitVarInsn(Opcodes.ALOAD, 0)
- mv.visitVarInsn(Opcodes.ALOAD, 0)
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, AresValue.LifeClass, "create", "(Ljava/lang/Object;)" + fieldDesc, false)
- mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldName, fieldDesc)
- mv.visitLabel(label)
- mv.visitVarInsn(Opcodes.ALOAD, 0)
- mv.visitFieldInsn(Opcodes.GETFIELD, className, fieldName, fieldDesc)
- mv.visitInsn(Opcodes.ARETURN)
- mv.visitMaxs(0, 0)
- mv.visitEnd()
- }
- MethodLifeCycleVisitor(MethodVisitor mv, MethodModel agent) {
- super(mv, agent)
- this.agent = agent
- }
- @Override
- void visitCode() {
- super.visitCode()
- visitVarInsn(Opcodes.ALOAD, 0)
- visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.agent.className, AresValue.GetLifeMethod, "()L" + AresValue.LifeClass + ";", false)
- for (int i = 0; i < this.agent.count; i++) loadArg(i)
- visitMethodInsn(Opcodes.INVOKEVIRTUAL, AresValue.LifeClass, this.agent.name, this.agent.desc, false)
- }
- }
|