Browse Source

add click agent

weiguo 7 years ago
parent
commit
cc9abdc354

+ 28 - 0
app/src/main/java/com/uddream/plugin/Agent.java

@@ -0,0 +1,28 @@
+package com.uddream.plugin;
+
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.Toast;
+
+/**
+ * Created by Glen on 2017/2/8.
+ */
+
+public class Agent {
+
+    public static void onClickPre(View view) {
+        Toast.makeText(view.getContext(), "agent click pre listener", Toast.LENGTH_LONG).show();
+    }
+
+    public static void onClick(View view) {
+        Toast.makeText(view.getContext(), "agent click listener", Toast.LENGTH_LONG).show();
+    }
+
+    public static void onCheckedChangedPre(CompoundButton view, boolean isChecked) {
+        Toast.makeText(view.getContext(), "agent check pre listener " + isChecked, Toast.LENGTH_LONG).show();
+    }
+
+    public static void onCheckedChanged(CompoundButton view, boolean isChecked) {
+        Toast.makeText(view.getContext(), "agent check listener " + isChecked, Toast.LENGTH_LONG).show();
+    }
+}

+ 20 - 4
app/src/main/java/com/uddream/plugin/MainActivity.java

@@ -4,17 +4,20 @@ import android.os.Bundle;
 import android.support.design.widget.FloatingActionButton;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
+import android.util.Log;
 import android.view.View;
-import android.widget.Toast;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
 
 import com.bumptech.glide.Glide;
+import com.uddream.library.Test;
+
+public class MainActivity extends AppCompatActivity implements View.OnClickListener, CompoundButton.OnCheckedChangeListener {
 
-public class MainActivity extends AppCompatActivity {
-    
     private View.OnClickListener listener = new View.OnClickListener() {
         @Override
         public void onClick(View v) {
-            Toast.makeText(MainActivity.this, "field listener", Toast.LENGTH_LONG).show();
+            System.out.print("field listener");
         }
     };
 
@@ -27,5 +30,18 @@ public class MainActivity extends AppCompatActivity {
         Glide.with(this);
         FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
         fab.setOnClickListener(listener);
+        fab.setOnClickListener(new Test());
+        fab.setOnClickListener(this);
+        new CheckBox(this).setOnCheckedChangeListener(this);
+    }
+
+    @Override
+    public void onClick(View v) {
+        System.out.print("onClick listener");
+    }
+
+    @Override
+    public void onCheckedChanged(CompoundButton v, boolean isChecked) {
+        System.out.print("onCheckedChanged listener");
     }
 }

+ 1 - 0
buildSrc/src/main/groovy/com/gradle/AresPlugin.groovy

@@ -1,5 +1,6 @@
 package com.gradle
 
+import com.gradle.ares.AresTransform
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 

+ 0 - 53
buildSrc/src/main/groovy/com/gradle/AresTransform.groovy

@@ -1,53 +0,0 @@
-package com.gradle
-
-import org.gradle.api.Project
-
-/**
- * Created by Glen on 2017/2/7.
- */
-
-public class AresTransform extends ModifyClassTransform {
-    public AresTransform(Project project) {
-        super(project);
-    }
-
-    @Override
-    protected void handleChangedFile(File input) {
-        String path = input.absolutePath.replace("/", "\\")
-        if (input.isFile()) {
-            debug("changed:" + input.absolutePath)
-            if (path.endsWith(".class")) {
-                modifyClass(input)
-            } else if (path.endsWith(".jar")) {
-                if (path.contains("exploded-aar")) {
-                    if (!path.contains("com.android.support")) {
-                        //需要处理的jar包
-                        File tmp = new File(input.getParent() + File.separator + "tmp")
-                        tmp.deleteOnExit()
-
-                        boolean modify = false
-                        if (!modify) JarZipUtil.unzipJar(input, tmp.absolutePath)
-                        tmp.eachFileRecurse { File file ->
-                            if (file.isFile()) {
-                                if (modifyClass(file)) {
-                                    modify = true
-                                }
-                            }
-                        }
-                        if (modify) JarZipUtil.zipJar(tmp.absolutePath, input)
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * 修改类文件
-     * @param clazz
-     * @return
-     */
-    private boolean modifyClass(File clazz) {
-        debug("modify:" + clazz.absolutePath)
-        return false
-    }
-}

+ 2 - 2
buildSrc/src/main/groovy/com/gradle/ModifyClassTransform.groovy

@@ -17,8 +17,8 @@ public abstract class ModifyClassTransform extends Transform {
     protected Logger logger;
 
     public ModifyClassTransform(Project project) {
-        this.project = project;
-        this.logger = Logging.getLogger(ModifyClassTransform.class);
+        this.project = project
+        this.logger = Logging.getLogger(ModifyClassTransform.class)
     }
 
     @Override

+ 72 - 0
buildSrc/src/main/groovy/com/gradle/ares/AresTransform.groovy

@@ -0,0 +1,72 @@
+package com.gradle.ares
+
+import com.gradle.JarZipUtil
+import com.gradle.ModifyClassTransform
+import org.gradle.api.Project
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.ClassWriter
+
+/**
+ * Created by Glen on 2017/2/7.
+ */
+
+public class AresTransform extends ModifyClassTransform {
+    public AresTransform(Project project) {
+        super(project);
+    }
+
+    @Override
+    protected void handleChangedFile(File input) {
+        String path = input.absolutePath.replace("/", "\\")
+        debug("changed:" + path)
+
+        if (input.isFile()) {
+            if (path.endsWith(".class")) {
+                modifyClass(input)
+            } else if (path.endsWith(".jar")) {
+                boolean modify = false
+                if (path.contains("exploded-aar") && !path.contains("exploded-aar\\com.android.support")) {
+                    modify = true
+                }
+
+                if (modify) {
+                    //需要处理的jar包
+                    File tmp = new File(input.getParent() + File.separator + "tmp")
+                    tmp.deleteOnExit()
+
+                    JarZipUtil.unzipJar(input, tmp.absolutePath)
+                    modify = false
+                    tmp.eachFileRecurse { File file ->
+                        if (file.isFile()) {
+                            if (modifyClass(file)) {
+                                modify = true
+                            }
+                        }
+                    }
+                    if (modify) JarZipUtil.zipJar(tmp.absolutePath, input)
+                }
+            }
+        }
+    }
+
+    /**
+     * 修改类文件
+     * @param clazz
+     * @return
+     */
+    private boolean modifyClass(File clazz) {
+        if (clazz.absolutePath.replace("\\", "/").endsWith(MethodAgentVisitor.AgentClass + ".class")) return
+
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS)
+        ClassReader cr = new ClassReader(clazz.bytes)
+        ClassAdapter adapter = new ClassAdapter(cw, project)
+        cr.accept(adapter, ClassReader.SKIP_DEBUG)
+
+        if (adapter.modify) {
+            FileOutputStream out = new FileOutputStream(clazz)
+            out.write(cw.toByteArray())
+            out.close()
+        }
+        return adapter.modify
+    }
+}

+ 57 - 0
buildSrc/src/main/groovy/com/gradle/ares/ClassAdapter.groovy

@@ -0,0 +1,57 @@
+package com.gradle.ares
+
+import org.gradle.api.Project
+import org.gradle.api.logging.Logger
+import org.gradle.api.logging.Logging
+import org.objectweb.asm.ClassVisitor
+import org.objectweb.asm.MethodVisitor
+import org.objectweb.asm.Opcodes
+
+/**
+ * Created by Glen on 2017/2/8.
+ */
+
+public class ClassAdapter extends ClassVisitor {
+    private Project project;
+    private Logger logger;
+
+    private boolean modify;
+    private int access;
+    private String superName;
+    private String[] interfaces;
+
+    public ClassAdapter(ClassVisitor cv, Project project) {
+        super(Opcodes.ASM5, cv)
+        this.project = project
+        this.logger = Logging.getLogger(ClassAdapter.class)
+    }
+
+    @Override
+    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+        super.visit(version, access, name, signature, superName, interfaces)
+        this.access = access
+        this.superName = superName
+        this.interfaces = interfaces
+        debug("class:" + name + "_" + superName + "_" + interfaces)
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions)
+        def agent = MethodAgentVisitor.getAgent(access, name, desc)
+        if (agent != null) {
+            modify = true
+            debug("method:" + access + "_" + name + "_" + desc)
+            return new MethodAgentVisitor(mv, agent)
+        }
+        return mv
+    }
+
+    boolean getModify() {
+        return modify
+    }
+
+    private void debug(def msg) {
+        this.logger.lifecycle(":" + this.project.name + ":" + msg)
+    }
+}

+ 66 - 0
buildSrc/src/main/groovy/com/gradle/ares/MethodAgentVisitor.groovy

@@ -0,0 +1,66 @@
+package com.gradle.ares
+
+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 MethodAgentVisitor extends GeneratorAdapter {
+    public final static String AgentClass = "com/uddream/plugin/Agent";
+
+    public final static Agent[] Modify = [
+            new Agent("onClick", "(Landroid/view/View;)V"),
+            new Agent("onCheckedChanged", "(Landroid/widget/CompoundButton;Z)V")
+    ] as Agent[]
+
+    public final static Agent getAgent(int access, String name, String desc) {
+        for (Agent item : Modify) {
+            if (item.name.equals(name) && item.desc.equals(desc)) {
+                item.access = access
+                return item
+            }
+        }
+        return null
+    }
+
+    private int pCount;
+    private Agent agent;
+
+    MethodAgentVisitor(MethodVisitor mv, Agent agent) {
+        super(Opcodes.ASM5, mv, agent.access, agent.name, agent.desc)
+        this.agent = agent
+        for (def item : agent.desc.substring(1, agent.desc.indexOf(")")).split(";")) {
+            if (!item.equals("")) this.pCount++
+        }
+    }
+
+    @Override
+    void visitCode() {
+        super.visitCode()
+        for (int i = 0; i < pCount; i++) loadArg(i)
+        visitMethodInsn(Opcodes.INVOKESTATIC, AgentClass, agent.name + "Pre", agent.desc, false)
+    }
+
+    @Override
+    public void visitInsn(int opcode) {
+        if (opcode == Opcodes.RETURN) {
+            for (int i = 0; i < pCount; i++) loadArg(i)
+            visitMethodInsn(Opcodes.INVOKESTATIC, AgentClass, agent.name, agent.desc, false)
+        }
+        super.visitInsn(opcode);
+    }
+
+    public static class Agent {
+        int access;
+        String name;
+        String desc;
+
+        Agent(String name, String desc) {
+            this.name = name
+            this.desc = desc
+        }
+    }
+}

+ 6 - 2
mylibrary/src/main/java/com/uddream/library/Test.java

@@ -1,10 +1,14 @@
 package com.uddream.library;
 
+import android.view.View;
+
 /**
  * Created by Glen on 2017/2/7.
  */
 
-public class Test {
-    public void log() {
+public class Test implements View.OnClickListener {
+    @Override
+    public void onClick(View v) {
+        System.out.print("test listener");
     }
 }