Hook技术:  Hook就是有一段程序逻辑一直走下去,我们可以捕获到其中间的一些逻辑,加于处理然后再让他接着执行下去;

比如Android里面的setOnclickListener这个方法. 正常我们是这样操作的

        TextView textView = findViewById(R.id.act_invoke_tv);        textView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(InvokeOnClickActivity.this, ((TextView)v).getText(), Toast.LENGTH_SHORT).show();            }        });

怎么在不改变这段代码的情况下,把里面的的Toast内容给替换掉

分析思路: 1肯定要用到动态代码,动态代码用到的是Proxy这个类

        Object proxyInstance = Proxy.newProxyInstance(getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() {            @Override            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                Toast.makeText(InvokeOnClickActivity.this, "已经hokd到方法了", Toast.LENGTH_SHORT).show();                return method.invoke(mOnClickListener, null);            }        });

等我们通过反射获取到textView设置的mClickListener的时候就将其替换

首先我们在setOnclickListener的时候传的是一个View.OnClickListener过去

   public void setOnClickListener(@Nullable OnClickListener l) {        if (!isClickable()) {            setClickable(true);        }        getListenerInfo().mOnClickListener = l;    }

这方法里面将我们传入的OnclickListener附值给了getListenerInfo()获取的类的一个成员变量,而getListenerInfo()这个方法获取的是ListenerInfo这个类,也就是说,在这里操作的是将我们设置的OnClickListener传给了ListenerInfo,是他里面的一个成员变量,

所以我们第一步就是获取到View里面的getListenerInfo这个方法

Class.forName这个方法可以获取到一个Class类,然后通过这个Class类获取到getListenerInfo这个方法,然后再执行这个方法代码如下

Class<?> viewClass = Class.forName("android.view.View");Method getListenerInfoMethod = viewClass.getDeclaredMethod("getListenerInfo");getListenerInfo.setAccessible(true);Object listenerInfo = getListenerInfoMethod.invoke(textView)

listenerInfo则就是通过VIew里的getListenerInfo获取到的对象  因为OnClickListener附给了ListenerInfo里的一个成员变量,这里我们继续通过反射获取到它的成员变量mOnClickListener

Object listenerInfoClass = Class.forName(android.view.View$ListenerInfo);//获取到名字为mOnClickListener的成员变量Field onClickListenerField = listenerInfoClass.getDeclaredField("mOnClickListener");//获取到原来设置的OnClickListener,其实可以不用这个,只是为了不影响正常逻辑,因为我们代理完了要重新//执行原来的方法Object mOnClickListener = onClickListenerField.get(listenerInfo);

最后一步就是替换操作了

onClickListenerField.set(listenerInfo,proxyInstance);这样就远的成自己的了,当我们点击Teview的点击事件的时候就会先走到我们代码的proxyInstance里面的invoke方法,

更多相关文章

  1. Android中bindService基本使用方法概述
  2. Unity 编辑器环境下不能正确加载Android Assetbundle 中的 Shade
  3. Android webView 获取、设置 cookie的方法
  4. Android常用控件的使用方法
  5. MPAndroidChart的一些问题解决方法
  6. 解决IE apk变成zip:Android 手机应用程序文件下载服务器 配置解决

随机推荐

  1. react native学习篇之图片学习
  2. Android(安卓)Ap 开发 设计模式第五篇:单
  3. Android相机、相册获取图片显示并保存到S
  4. android程序---->android多线程下载(一)
  5. Android(安卓)APK 瘦身处理
  6. Android原生和React Native 混合旧项目的
  7. Android(安卓)Studio 中超级常用的快捷键
  8. Android(安卓)屏幕适配解决方案汇总
  9. 第八章 Libgdx输入处理(3)输入设备
  10. Android(安卓)性能优化工具集合