Android Hook技术的简单实现

Android Hook技术的简单实现一、什么是Hook技术Android程序有一套特有的事件分发机制,都是按既定程序从前往后执行的。Hook技术就是利用反射和代理,在既定程序中插入我们自己写的程序。比如,我们想在App所有的点击事件中添加播放音乐的效果。所有控件的点击事件,分发流程都是系统已经写好了,这时我们怎么做到在其中插入我们的播放音乐的效果呢?让我们拭目以待!二、如何寻找Hook点1.尽量选择静态变量和单例对象,因为一旦创建对象,他们不容易变化,非常容易定位。2.尽量Hookpublic的对象和方法三、Hook过程选

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

一、什么是Hook 技术

Android 程序有一套特有的事件分发机制,都是按既定程序从前往后执行的。Hook 技术就是利用反射和代理,在既定程序中插入我们自己写的程序。比如,我们想在某个View的点击事件中添加播放音乐的效果。控件的点击事件,分发流程都是系统已经写好了,这时我们怎么做到在其中插入我们的播放音乐的效果呢?

二、如何寻找Hook点

1.尽量选择静态变量和单例对象,因为一旦创建对象,他们不容易变化,非常容易定位。
2.尽量Hook public的对象和方法

三、Hook过程

选中到了合适的Hook点后,选择合适的代理方式,如果是接口就可以用动态代理,然后偷梁换柱,用代理对象替换原始对象。

四、Hook View的点击事件

先看看View 点击事件的源码

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

由代码可以看出,我们正常设置进去的OnClickListener是保存在ListenerInfo里面的。
如果我们可以通过反射将这个ListenerInfo里面的mOnClickListener 替换成我们自定义的OnClickListener是不是就可以实现我们目的了。接下来我们试试!
先看看通过反射修改对象属性的API

field.set(Object obj, Object value) 
  • field是我们要修改的变量的属性,也就是mOnClickListener
  • obj就是要修改的对象,就是ListenerInfo
  • value就是要替换mOnClickListener 的新值

接下来围绕准备这几个变量,我们来写代码

 private void hookOnClickListener(View view) { 
   
        try { 
   
            // 得到待hook view 的 ListenerInfo 对象
            Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");
            getListenerInfo.setAccessible(true);
            Object listenerInfo = getListenerInfo.invoke(view);
            // 得到 原始的 mOnClickListener 对象
            Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");
            Field mOnClickListener = listenerInfoClz.getDeclaredField("mOnClickListener");
            mOnClickListener.setAccessible(true);
            View.OnClickListener originOnClickListener = (View.OnClickListener) mOnClickListener.get(listenerInfo);
            // 用自定义的 hookedOnClickListener 替换原始的 mOnClickListener
            View.OnClickListener hookedOnClickListener = new HookOnClickListener(originOnClickListener);
            mOnClickListener.set(listenerInfo, hookedOnClickListener);
        } catch (Exception e) { 
   
            Log.d(TAG, "hook clickListener failed!: ");
        }
    }

自定义的HookOnClickListener

 class HookOnClickListener implements View.OnClickListener { 
   
        private View.OnClickListener origin;

        HookOnClickListener(View.OnClickListener origin) { 
   
            this.origin = origin;
        }

        @Override
        public void onClick(View v) { 
   
            Log.d(TAG,"执行点击事件之前");
            if (origin != null) { 
   
                origin.onClick(v);
            }
            Log.d(TAG,"执行点击事件之后");
        }
    }

在MainActivity中的使用

 @Override
    protected void onCreate(Bundle savedInstanceState) { 
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvHook = findViewById(R.id.tv_hook);
        tvHook.setOnClickListener(new View.OnClickListener() { 
   
            @Override
            public void onClick(View v) { 
   
                Log.d(TAG,"tvHook 的点击事件");
            }
        });
        hookOnClickListener(tvHook);
    }

点击tvHook 看看输出结果

/com.example.hook D/MainActivity: 执行点击事件之前
/com.example.hook D/MainActivity: tvHook 的点击事件
/com.example.hook D/MainActivity: 执行点击事件之后

看到这里我们已经成功Hook到了View的点击事件

五、Hook注意点

Android 的API版本比较多,各个厂家也对系统有不同程度的定制,所以类和方法有可能不太一样,这就要求我们做好兼容。

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

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

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


相关推荐

  • TinyXML2 入门教程

    TinyXML2 入门教程TinyXML2是simple、small、efficient开源的C++XML文件解析库,可以很方便的应用到现有的项目之中。非常适合存储简单数据,配置文件,对象序列化等数据量不是很大的操作。TinyXML2详细介绍与源码获取方法详见:TinyXML2官网。

    2022年4月26日
    33
  • idea使用git stash

    idea使用git stashgitstash当我们使用git时,常遇到在自己分支上开发到一半,不想commit,但又不得不切换到别的分支进行操作,为了保留本地的修改git,提供了gitstash的相关命令,可以用来保护现场。idea使用gitstash例如我在dev分支尚未开发完,文件还未commit,我又必须切换至主分支进行bug修复,于是我们可以使用gitstashstash以后文件会回到改动前的…

    2022年6月23日
    58
  • e6600相当于amd_cpu核心电压

    e6600相当于amd_cpu核心电压据消费调研中心ZDC统计结果显示,2006年3月最受用户关注的前十款AMDCPU中,Athlon64和Sempron两大系列产品平分秋色,各有五款产品入围。具体产品排行如下图所示。(图)2006年3月最受用户关注的前十款AMDCPU排名产品名称报价L2缓存(KB)插槽类型主频(MHz)1¥990512Socket93918003¥765512Socket93918005¥1,120512S…

    2022年9月2日
    5
  • python能开发arm_获得通用技能的方法

    python能开发arm_获得通用技能的方法看了很多资料介绍如何将python移植到嵌入式设备当中,但总感觉杂乱五章,还移植不成功,但是经过我的多方摸索,成功的探索出了一条阳光大道,供各位网友借鉴参考。我采用的方法可以成功移植python2.7以后的所有版本。第一步:从官网下载源码.并把解压放在/opt第二步:在/Python-3.4.5目录下新建一键移植脚本,并执行内容如下:(执行完会报错某某模块内没安装,这个不耽误,…

    2022年10月10日
    0
  • ArrayDeque in Java[通俗易懂]

    ArrayDeque in Java[通俗易懂]ArrayDequeinJavaArrayDequeinJavaprovidesawaytoapplyresizable-arrayinadditiontotheimplementationoftheDequeinterface.ItisalsoknownasArrayDoubleEndedQueueorArrayDeck.Thi…

    2022年9月20日
    0
  • jQuery图片轮播特效

    效果预览:http://hovertree.com/texiao/jquery/51/这款特效有缩略图,包含文字说明和链接,可以自动播放,也可以手动切换。使用的jQuery库版本为1.12.3,

    2021年12月22日
    45

发表回复

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

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