MethodLifeCycleVisitor.groovy 5.2 KB

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