package com.didichuxing.doraemonkit.plugin.bytecode; import com.didichuxing.doraemonkit.plugin.DokitExtUtil; import com.didichuxing.doraemonkit.plugin.bytecode.method.bigimg.FrescoMethodAdapter; import com.didichuxing.doraemonkit.plugin.bytecode.method.bigimg.GlideMethodAdapter; import com.didichuxing.doraemonkit.plugin.bytecode.method.bigimg.GlideTransformMethodAdapter; import com.didichuxing.doraemonkit.plugin.bytecode.method.bigimg.ImageLoaderMethodAdapter; import com.didichuxing.doraemonkit.plugin.bytecode.method.bigimg.PicassoMethodAdapter; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; /** * Created by jint on 13/12/2019. * 类访问器 */ public final class DokitBigImageClassAdapter extends ClassVisitor { /** * 当前类型 */ private String className; /** * 当前类的父类 假如存在的话 */ private String superName; /** * @param cv cv */ public DokitBigImageClassAdapter(final ClassVisitor cv) { super(Opcodes.ASM7, cv); } @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.className = name; this.superName = superName; } /** * Visits a method of the class. This method must return a new {@link MethodVisitor} * instance (or {@literal null}) each time it is called, i.e., it should not return a previously * returned visitor. * * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if * the method is synthetic and/or deprecated. * @param methodName the method's name. * @param desc the method's descriptor (see {@link Type}). * @param signature the method's signature. May be {@literal null} if the method parameters, * return type and exceptions do not use generic types. * @param exceptions the internal names of the method's exception classes (see {@link * Type#getInternalName()}). May be {@literal null}. * @return an object to visit the byte code of the method, or {@literal null} if this class * visitor is not interested in visiting the code of this method. */ @Override public MethodVisitor visitMethod(int access, String methodName, String desc, String signature, String[] exceptions) { //从传进来的ClassWriter中读取MethodVisitor MethodVisitor mv = cv.visitMethod(access, methodName, desc, signature, exceptions); //开关被关闭 不插入代码 if (!DokitExtUtil.getInstance().isDokitPluginSwitch()) { return mv; } if (!DokitExtUtil.getInstance().isBigImgSwitch()) { return mv; } //Glide v4字节码替换 glide v4.9 通过init注入 4.11.0 通用构造函数 if (className.equals("com/bumptech/glide/request/SingleRequest") && (methodName.equals("init") || methodName.equals("")) && desc != null) { log(className, access, methodName, desc, signature); //创建MethodVisitor代理 return mv == null ? null : new GlideMethodAdapter(mv, access, methodName, desc); } //Glide v4字节码替换 transform 代码注入 // if (className.equals("com/bumptech/glide/request/BaseRequestOptions") && methodName.equals("transform") && desc != null) { // if (desc.equals("(Lcom/bumptech/glide/load/Transformation;Z)Lcom/bumptech/glide/request/BaseRequestOptions;")) { // log(className, access, methodName, desc, signature); // //创建MethodVisitor代理 // return mv == null ? null : new GlideTransformMethodAdapter(mv, access, methodName, desc); // } // } //Glide v3字节码替换 // if (className.equals("com/bumptech/glide/GenericRequestBuilder") && methodName.equals("listener") && desc != null) { // log(className, access, methodName, desc, signature); // //创建MethodVisitor代理 // return mv == null ? null : new GlideV3MethodAdapter(mv, access, methodName, desc); // } //Picasso 字节码替换 if (className.equals("com/squareup/picasso/Request") && methodName.equals("") && desc != null) { log(className, access, methodName, desc, signature); // (Lcom/bumptech/glide/load/Transformation;Z)Lcom/bumptech/glide/request/BaseRequestOptions; //创建MethodVisitor代理 return mv == null ? null : new PicassoMethodAdapter(mv, access, methodName, desc); } //Fresco字节码替换 if (className.equals("com/facebook/imagepipeline/request/ImageRequest") && methodName.equals("") && desc != null) { log(className, access, methodName, desc, signature); //创建MethodVisitor代理 return mv == null ? null : new FrescoMethodAdapter(mv, access, methodName, desc); } //imageLoader字节码替换 if (className.equals("com/nostra13/universalimageloader/core/ImageLoadingInfo") && methodName.equals("") && desc != null) { log(className, access, methodName, desc, signature); //创建MethodVisitor代理 return mv == null ? null : new ImageLoaderMethodAdapter(mv, access, methodName, desc); } //过滤所有类中当前方法中所有的字节码 return mv; } /** * 获取形参个数 * * @param desc * @return */ private int getParamsSize(String desc) { //(Landroid/app/Application;Ljava/util/List;Ljava/lang/String;)V 包含3个参数的install方法实例 if (desc == null || desc.equals("")) { return 0; } return desc.split(";").length - 1; } /** * 日志输出 * * @param className * @param access * @param name * @param desc * @param signature */ private void log(String className, int access, String name, String desc, String signature) { System.out.println("DokitBigImageClassAdapter===matched====>" + " className===" + className + " access===" + access + " methodName===" + name + " desc===" + desc + " signature===" + signature); } }