Hook技术看这篇就够了[通俗易懂]

Hook技术看这篇就够了[通俗易懂]   相信很多搞机的朋友都玩过Xposed,它实现了很多不可思议的功能。它是怎么实现的呢?这里就得提到我们的Hook技术了。    关于Android中的Hook机制,大致有两个方式: 要root权限,直接Hook系统,可以干掉所有的App。 免root权限,但是只能Hook自身,对系统其它App无能为力。   时间所限,这里不展开了。   知识点: …

大家好,又见面了,我是你们的朋友全栈君。

    相信很多搞机的朋友都玩过Xposed, 它实现了很多不可思议的功能。它是怎么实现的呢?这里就得提到我们的Hook技术了。

    关于 Android 中的 Hook 机制,大致有两个方式:

  •   要 root 权限,直接 Hook 系统,可以干掉所有的 App。
  •   免 root 权限,但是只能 Hook 自身,对系统其它 App 无能为力。

    时间所限,这里不展开了。

    知识点:

    今天主要讲的是利用hook技术,将点击事件劫持,做点啥呢?你可以随意,我这里是将双击给屏蔽了。免得点击过快打开多个界面。

1、寻找Hook点

    这一步比较关键,也是个难点。Android中主要是依靠分析系统源码类来做到的,首先我们得找到被Hook的对象,我称之为Hook点;什么样的对象比较好Hook呢?自然是容易找到的对象。什么样的对象容易找到?静态变量和单例;在一个进程之内,静态变量和单例变量是相对不容易发生变化的,因此非常容易定位,而普通的对象则要么无法标志,要么容易改变。我们根据这个原则找到所谓的Hook。

去看setOnClickListener里面做了什么?

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

看完了上面,就能猜到我们设置的Listener最终是被赋值给ListenerInfo的mOnClickListener成员了,ListenerInfo的实例可以说是信息的载体,那么很简单,只要把mOnClickListener,在ListenerInfo中还有mOnLongClickListener,mOnFocusChangeListener两个成员,分别对应了长按事件与焦点变化事件,所以处理长按事件与焦点变化事件与此类似。

public class HookViewClickUtil { 
   

    public static HookViewClickUtil getInstance() {
        return UtilHolder.mHookViewClickUtil;
    }

    private static class UtilHolder { 
   
        private static HookViewClickUtil mHookViewClickUtil = new HookViewClickUtil();
    }

    public static void hookView(View view) {
        try {
            Class viewClazz = Class.forName("android.view.View");
            //事件监听器都是这个实例保存的
            Method listenerInfoMethod = viewClazz.getDeclaredMethod("getListenerInfo");
            if (!listenerInfoMethod.isAccessible()) {
                listenerInfoMethod.setAccessible(true);
            }
            Object listenerInfoObj = listenerInfoMethod.invoke(view);

            Class listenerInfoClazz = Class.forName("android.view.View$ListenerInfo");

            Field onClickListenerField = listenerInfoClazz.getDeclaredField("mOnClickListener");

            if (!onClickListenerField.isAccessible()) {
                onClickListenerField.setAccessible(true);
            }
            View.OnClickListener mOnClickListener = (View.OnClickListener) onClickListenerField.get(listenerInfoObj);
            //自定义代理事件监听器
            View.OnClickListener onClickListenerProxy = new OnClickListenerProxy(mOnClickListener);
            //更换
            onClickListenerField.set(listenerInfoObj, onClickListenerProxy);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //自定义的代理事件监听器
    private static class OnClickListenerProxy implements View.OnClickListener { 
   

        private View.OnClickListener object;

        private int MIN_CLICK_DELAY_TIME = 1000;

        private long lastClickTime = 0;

        private OnClickListenerProxy(View.OnClickListener object) {
            this.object = object;
        }

        @Override
        public void onClick(View v) {
            //点击时间控制
            long currentTime = Calendar.getInstance().getTimeInMillis();
            if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {
                lastClickTime = currentTime;
                Log.e("OnClickListenerProxy", "OnClickListenerProxy");
                if (object != null) object.onClick(v);
            }
        }
    }
}

使用起来也是非常简单,首先在MainActivity的View渲染完毕的时候进行注入,即在 getWindow().getDecorView().post()中。

public class MainActivity extends Activity { 
   

    private Button  btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final View btn = findViewById(R.id.btn);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e("MainActivity","Button 被点击了");
            }
        });

        getWindow().getDecorView().post(new Runnable() {
            @Override
            public void run() {
                HookViewClickUtil.hookView(btn);
            }
        });
    }
}

Hook技术看这篇就够了[通俗易懂]

原文出处:https://blog.csdn.net/u013263323/article/details/55094822

    

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141211.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • box-shadow(盒子阴影)

    box-shadow(盒子阴影)深入理解css3新增属性之box-shadow盒子阴影,它可以向框添加一个或多个阴影

    2022年7月2日
    22
  • vmware虚拟机重装系统_ubuntu下安装虚拟机

    vmware虚拟机重装系统_ubuntu下安装虚拟机VMware下载地址:https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html下载之后按步骤安装即可。安装完成后需要密钥,这里给出VMwareWorkstationPro16的密钥:YF390-0HF8P-M81RQ-2DXQE-M2UT6ZF71R-DMX85-08DQY-8YMNC-PPHV8密钥输入完成就可永久使用。ubuntu:首先下载Ubuntu的镜像,我下载的是ubuntu

    2025年11月18日
    4
  • 全面介绍Android Studio中Git 的使用(一)

    全面介绍Android Studio中Git 的使用(一)一、Git与GitHub这里首先介绍下Git与GitHub是什么东西,他们之间有何区别呢?Git:分布式版本控制系统,最初用在Linux上,可以和SVN、CVS等作为同一个概念理解,目前世界上最先进的分布式版本控制系统(没有之一)。GitHub:基于Git的项目托管平台,简单的说就是一个网站,通过注册账号后,可以使用Git服务,它提供了可以在上面创建资源仓库的Web页面,通过shell命令或者图形用户界面可以和远程项目同步更新,对项目进行管理。还是不太清楚?就是一个项目由多个人一起干,开发中对于

    2022年7月15日
    18
  • 【android】在eclipse中查看genymotion模拟器的sd卡文件夹

    【android】在eclipse中查看genymotion模拟器的sd卡文件夹

    2022年2月4日
    47
  • Atitit.提升api兼容性的方法 v3 q326

    Atitit.提升api兼容性的方法 v3 q326

    2021年9月13日
    81
  • Haier数字可视对讲系列(转)「建议收藏」

    Haier数字可视对讲系列(转)「建议收藏」数字可视对讲系列楼宇可视对讲这一家庭安防设备是智能化小区建设的必要项目之一,也是家居安全的护身符。对讲系统是在各小区、单元门入口安装防盗门和对讲装置,其主要目的是实现访客与住户可视、对讲。住户可通过系统遥控开启防盗门,从而有效…

    2022年6月22日
    53

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号