MethodLifeCycleVisitor.groovy 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package com.gradle.ares
  2. import org.objectweb.asm.ClassVisitor
  3. import org.objectweb.asm.FieldVisitor
  4. import org.objectweb.asm.Label
  5. import org.objectweb.asm.MethodVisitor
  6. import org.objectweb.asm.Opcodes
  7. import org.objectweb.asm.commons.GeneratorAdapter
  8. /**
  9. * Created by Glen on 2017/2/8.
  10. */
  11. public class MethodLifeCycleVisitor extends MethodBaseVisitor {
  12. public final static String[] SuperClass = [
  13. "android/app/Activity",
  14. "android/support/v4/app/FragmentActivity",
  15. "android/support/v7/app/AppCompatActivity",
  16. "android/support/v4/app/Fragment",
  17. "android/support/v4/app/ListFragment",
  18. "android/support/v4/app/DialogFragment",
  19. "android/app/Fragment",
  20. "android/app/ListFragment",
  21. "android/app/DialogFragment"
  22. ] as String[]
  23. public final static MethodModel[] Modify = [
  24. new MethodModel("onCreate", "(Landroid/os/Bundle;)V", 1),
  25. new MethodModel("onResume", "()V", 0),
  26. new MethodModel("onPause", "()V", 0),
  27. new MethodModel("onDestroy", "()V", 0),
  28. new MethodModel("onSaveInstanceState", "(Landroid/os/Bundle;)V", 1),
  29. new MethodModel("onRestoreInstanceState", "(Landroid/os/Bundle;)V", 1),
  30. new MethodModel("setUserVisibleHint", "(Z)V", 1),
  31. new MethodModel("onHiddenChanged", "(Z)V", 1)
  32. ] as MethodModel[]
  33. public
  34. static MethodModel getAgent(int access, String className, String superName, String name, String desc) {
  35. for (MethodModel item : Modify) {
  36. if (item.name.equals(name) && item.desc.equals(desc)) {
  37. item.access = access
  38. item.className = className
  39. item.superName = superName
  40. return item
  41. }
  42. }
  43. return null
  44. }
  45. public
  46. static void addMethods(Set<MethodModel> agentSet, String className, String superName, ClassVisitor cv) {
  47. addLifeCycleFieldMethod(className, cv)
  48. for (MethodModel agent : Modify) {
  49. if (!agentSet.contains(agent)) {
  50. //method
  51. MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, agent.name, agent.desc, null, null)
  52. GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ASM5, mv, Opcodes.ACC_PUBLIC, agent.name, agent.desc)
  53. adapter.visitCode()
  54. adapter.loadThis()
  55. adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, AresValue.GetLifeMethod, "()L" + AresValue.LifeClass + ";", false)
  56. for (int i = 0; i < agent.count; i++) adapter.loadArg(i)
  57. adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, AresValue.LifeClass, agent.name, agent.desc, false)
  58. adapter.loadThis()
  59. for (int i = 0; i < agent.count; i++) adapter.loadArg(i)
  60. adapter.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, agent.name, agent.desc, false)
  61. adapter.visitInsn(Opcodes.RETURN)
  62. adapter.visitMaxs(0, 0)
  63. adapter.visitEnd()
  64. }
  65. }
  66. }
  67. /**
  68. * 注入代理字段及初始化方法
  69. * @param cv
  70. */
  71. private static void addLifeCycleFieldMethod(String className, ClassVisitor cv) {
  72. //desc
  73. String fieldName = "\$lifeCycleAresDelegate"
  74. String fieldDesc = "L" + AresValue.LifeClass + ";"
  75. //field
  76. FieldVisitor fv = cv.visitField(Opcodes.ACC_PUBLIC, fieldName, fieldDesc, null, null)
  77. fv.visitEnd()
  78. //method
  79. MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, AresValue.GetLifeMethod, "()" + fieldDesc, null, null)
  80. mv.visitCode()
  81. mv.visitVarInsn(Opcodes.ALOAD, 0)
  82. mv.visitFieldInsn(Opcodes.GETFIELD, className, fieldName, fieldDesc)
  83. Label label = new Label()
  84. mv.visitJumpInsn(Opcodes.IFNONNULL, label)
  85. mv.visitVarInsn(Opcodes.ALOAD, 0)
  86. mv.visitVarInsn(Opcodes.ALOAD, 0)
  87. mv.visitMethodInsn(Opcodes.INVOKESTATIC, AresValue.LifeClass, "create", "(Ljava/lang/Object;)" + fieldDesc, false)
  88. mv.visitFieldInsn(Opcodes.PUTFIELD, className, fieldName, fieldDesc)
  89. mv.visitLabel(label)
  90. mv.visitVarInsn(Opcodes.ALOAD, 0)
  91. mv.visitFieldInsn(Opcodes.GETFIELD, className, fieldName, fieldDesc)
  92. mv.visitInsn(Opcodes.ARETURN)
  93. mv.visitMaxs(0, 0)
  94. mv.visitEnd()
  95. }
  96. MethodLifeCycleVisitor(MethodVisitor mv, MethodModel agent) {
  97. super(mv, agent)
  98. this.agent = agent
  99. }
  100. @Override
  101. void visitCode() {
  102. super.visitCode()
  103. visitVarInsn(Opcodes.ALOAD, 0)
  104. visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.agent.className, AresValue.GetLifeMethod, "()L" + AresValue.LifeClass + ";", false)
  105. for (int i = 0; i < this.agent.count; i++) loadArg(i)
  106. visitMethodInsn(Opcodes.INVOKEVIRTUAL, AresValue.LifeClass, this.agent.name, this.agent.desc, false)
  107. }
  108. }