美文网首页程序员
Javassist in Android(一) 过滤onClic

Javassist in Android(一) 过滤onClic

作者: 和平菌 | 来源:发表于2017-11-14 18:04 被阅读0次

    通过解析所有的类,过滤出onClick方法用来注入我们的事件统计代码。 没有逻辑性的问题,就直接上代码了。

    由于Javassist的封装比较复杂,首先我要定义两个实体,存放我解析出来需要用到的Method属性。

    public class IMethod {
        
        private String name;
        private List<IMethodParam> params = new ArrayList<>();
        private String returnType;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        public List<IMethodParam> getParams() {
            return params;
        }
        public void setParams(List<IMethodParam> params) {
            this.params = params;
        }
        public String getReturnType() {
            return returnType;
        }
        public void setReturnType(String returnType) {
            this.returnType = returnType;
        }
        
        public void addParam(IMethodParam param) {
            if(param != null){
                params.add(param);
            }
        }
    }
    
    
    public class IMethodParam {
        private String type;//the typename of param, example:android.view.View
        private String name;//the name of param, example:v
        
        
        public IMethodParam() {
            super();
        }
        public IMethodParam(String type, String name) {
            super();
            this.type = type;
            this.name = name;
        }
        public String getType() {
            return type;
        }
        public void setType(String type) {
            this.type = type;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof IMethodParam) {
                IMethodParam param = (IMethodParam) obj;
                return (type != null && name != null//
                        && param != null//
                        && param.getType() != null//
                        && param.getName() != null//
                        && type.equals(param.getType())//
                        && name.equals(param.getName()));//
            }
            
            return super.equals(obj);
        }
        
        @Override
        public int hashCode() {
            if(type != null && name != null)
                return (type + name).hashCode();
            return super.hashCode();
        }
    
    }
    
    

    接着我们要解析Mehod,我们主要需要方法名,参数类型的名称,参数的名称以及返回值的类型名称

    public static IMethod parse(CtMethod method){
            if(method != null){
                IMethod iMethod = new IMethod();
                iMethod.setName(method.getName());
                
                /***
                 * 获取参数的类型和值
                 */
                try {
                    CtClass[] parameterTypes = method.getParameterTypes();
                    if(parameterTypes != null && parameterTypes.length > 0){
                        int len = parameterTypes.length;
                        String[] paramNames = getMethodParamNames(method);
                        if(paramNames != null && paramNames.length >= len){
                            for (int i = 0; i < parameterTypes.length; i++) {
                                IMethodParam param = new IMethodParam();
                                param.setType(parameterTypes[i].getName());
                                param.setName(paramNames[i]);
                                
                                iMethod.addParam(param);
                            }
                        }
                    }
                    
                    CtClass returnType = method.getReturnType();
                    if(returnType != null){
                        iMethod.setReturnType(returnType.getName());
                    }
                    
                } catch (NotFoundException e) {
                    e.printStackTrace();
                }
                
                return iMethod;
            }
            return null;
        }
    
    
    public static String[] getMethodParamNames(CtMethod cm) {
            MethodInfo methodInfo = cm.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute
                    .getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
                return null;
            }
            String[] paramNames = null;
            
            try {
                CtClass[] parameterTypes = cm.getParameterTypes();
                if(parameterTypes != null && parameterTypes.length > 0){
                    paramNames = new String[parameterTypes.length];
                }
            } catch (NotFoundException e) {
                e.printStackTrace();
                return null;
            }
            int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
            for (int i = 0; i < paramNames.length; i++) {
                paramNames[i] = attr.variableName(i + pos);
            }
            return paramNames;
        }
    
    

    剩下的就是根据解析出来的内容来判断是否是onClick方法

    public static final String ONCLICK_METHOD_NAME = "onClick";
        public static final String ONCLICK_METHOD_PARAM_TYPE = "android.view.View";
        public static final String ONCLICK_METHOD_RETURN_TYPE = "void";
        public static boolean isOnClick(IMethod method){
            if(method != null){
                String name = method.getName();
                List<IMethodParam> params = method.getParams();
                String returnType = method.getReturnType();
                if(notNul(name) && notNul(returnType) && notNul(params)){
                    IMethodParam param = params.get(0);
                    return ONCLICK_METHOD_NAME.equals(name)
                            && ONCLICK_METHOD_RETURN_TYPE.equals(returnType)
                            && ONCLICK_METHOD_PARAM_TYPE.equals(param.getType());
                }
            }
            return false;
        }
        
        public static boolean notNul(String s){
            return s!= null && !"".equals(s);
        }
        
        
        public static boolean notNul(List list){
            return list != null && list.size() > 0;
        }
    

    相关文章

      网友评论

        本文标题:Javassist in Android(一) 过滤onClic

        本文链接:https://www.haomeiwen.com/subject/xxbfvxtx.html