登录

去注册

登录

注册

去登录

注册

每日一问 思考一下如果捕获一个 Activity页面上所有的点击行为?

xiaoyang   2019-05-23   收藏

思考一下如果捕获一个 Activity页面上所有的点击行为?


1. 有哪些可选方案?


2. 分别有什么优缺点?


3. 注意别忘了动态增加的 View,以及 Dialog 等。

6

可选方案现在想到的有:

     1. Activity中重写dispatchTouchEvent方法,监听ACTION_DOWN和ACTION_UP,然后判断距离差,小于一定距离则视为点击;

    2. 添加一个透明的全屏View到WindowManager中,用来监听和转发TouchEvent,并且重写目标Activity的onWindowFocusChanged方法,每当这个方法被回调,证明有可能是Dialog出现或关闭,因为Dialog.show()的原理其实也是WindowManager.addView,所以这时候需要把刚刚添加到WindowManager的透明View,重新置顶一下:先remove,再add,这样就始终在最上面了;

    3. 借助AccessibilityService来监听VIEW_CLICKED事件;

    4. 所有需要被监听的View,主动发通知: "我被点击了" ;


各自的优缺点:

    1. 重写dispatchTouchEvent方法,优点是方便快捷。缺点是监听不到已显示的Dialog。

    2. 添加透明View到WindowManager中,优点是能监听到显示的Dialog。缺点显而易见,就是6.0系统以上都需要申请权限(因为这是悬浮窗),对用户来说不太友好。

    3. 使用AccessibilityService的话,优点是精准,不需要自己写判断是否为点击的逻辑,缺点跟上面的差不多,就是需要用户到设置里面开启辅助功能。

    4. 这个方法可以说是最完美,也可以说是最愚蠢,缺点是非常麻烦,优点的话,就不用申请权限之类的咯。。。

回复
yihu5566 : @陈小缘 

那就是所有需要监听的view都注册点击事件,然后用asp监听click事件了吧。 @Around("execution(* android.view.View.OnClickListener.onC  ...查看更多

2019-05-22 回复
陈小缘 : @残页 

噢,学习了,感谢分享~

2019-05-22 回复
残页 : @陈小缘 

第四种方案如果加上类似AspectJ的埋点框架实现自动化还是可行的

2019-05-22 回复
3

一开始想的也是dispatchTouchEvent,但是有人已经说明了无法监听Dialog;

后来想的是点击事件要想分发进来必定需要WMS与应用交互,于是乎想到了反射设置本地的WindowManager中保存回调变量;还有就是事件要想进来必定会经过主线程的Looper,处理这些事件的Handler保存在ActivityThread的mH变量,那么反射设置一个我们自己的Handler进行处理或者设置Handler的Callback处理都是非常不错的选择,然而这种方法需要使用者对整个分发流程非常了解,门槛太高;还有就是该方案稳定性不够好

然后我想到了VM层面的hook,现在已经有很多成熟的hook框架了,比如epic,直接hook掉View的performClick方法就行;这种方法个人觉得很不错,唯一的问题就是hook方案的稳定性。

回复
1

1.给根布局命名个name,然后重写他的onClick方法。缺点是如果内部有button或者checkbox的子控件,点到上面焦点会被抢走。

2.重写当前activity的onTouchEvent方法,缺点是无法区分此次触摸是点击还是长按。

3.怎么去捕获添加的dialog的焦点,当dialog打开后,直接悬与最上层,怎么捕获?

回复
0

1.对activity捕获点击事件其实是对activity根view的点击监听。这样给它添加一个dispatchTouchEvent(),判断点击相隔的时间,如果符合点击就行。

  1. 对所有的点击时间进行拦截。用asp拦截
  2. 对这个页面的所有子view都添加点击时间监听
回复
0

hook,替换掉系统的点击实现

回复
0

可参考:Android全埋点 

回复
0

    我只想到了  Activity中重写dispatchTouchEvent方法   看到其他回答感觉又店高深

回复
0

应该是可以在Activity中到dispatchTouchEvent中捕捉到事件吧。

回复
0
publicabstract booleansuperDispatchTouchEvent(MotionEvent event);
 

publicabstractbooleansuperDispatchTrackballEvent(MotionEvent event);
 

publicabstractbooleansuperDispatchGenericMotionEvent(MotionEvent event);
回复
0

自己重写activity的事件分发函数?然后在里面判断?

回复

删除留言

确认删除留言,会导致相关评论丢失?

取消 确定