Android 滑动事件消费监控,Debug 环境下通用思路

Android Debug 环境下滑动事件消费监控通用思路

背景

Android 开发中,经常会遇到滑动事件冲突。在一些简单的场景下,我们如果能够知道是那个 View 拦截了事件,那我们能够很容易得解决。解决方法通常就是内部拦截法或者外部拦截法。ViewPager,ScrollView 嵌套ViewPager滑动冲突解决

然而,在一些复杂场景下,比如在直播间。很多时候,我们很难定位到是哪个 View 拦截了事件。有时候排查起来比较困难,于是,我在想,有没有一些方法,可以监控到滑动事件,点击事件被哪些 View 消费了。

徐公带你学 Android

答案当然是可以的,下面让我们一起来看看怎样实现?

实现思路

在 Android 当中,我们知道, View 的事件分发机制,主要有几个方法

  • dispatchTouchEvent
  • onInterceptTouchEvent
  • onTouchEvent

当然,还有一个 setOnTouchListener。

事件分发机制这里就不展开了,有兴趣的可以看这篇文章 Android面试老生常谈的 View 事件分发机制,看这一篇就够了

如果我们能够 hook 所有的 dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent 方法,还有 view.setOnTouchListener ,这样, 事件被哪个 View 消费,拦截了,那我们是不是就能够知道呢?

说干就干,那我们要怎么 Hook 所有的 View 事件的相应方法呢?想到的有两种方式

  • 借助 transform 进行插桩,比较麻烦,这里暂不展开讲述
  • 借助一些类似于 xpose 之类的框架,进行动态 hook

这里,为了快速接入,我们采用了 epic 这个框架:https://github.com/tiann/epic

Epic 是一个在虚拟机层面、以 Java Method 为粒度的 运行时 AOP Hook 框架。简单来说,Epic 就是 ART 上的 Dexposed(支持 Android 5.0 ~ 11)。

它可以拦截本进程内部几乎任意的 Java 方法调用,可用于实现 AOP 编程、运行时插桩、性能分析、安全审计等。

具体实现

比如说,我们要 Hook ViewGroup 的 onInterceptTouchEvent 事件,那么我们可以这样写

 private fun hookViewGroup(methodName: String = "onInterceptTouchEvent") {DexposedBridge.hookAllMethods(ViewGroup::class.java, methodName,object : XC_MethodHook() {override fun beforeHookedMethod(param: MethodHookParam?) {super.beforeHookedMethod(param)param ?: returnval name = param.method.nameif (name != methodName) {Log.w(TAG, "beforeHookedMethod: name is $name")return}printCommon(param, name, "before")}override fun afterHookedMethod(param: MethodHookParam?) {super.afterHookedMethod(param)param ?: returnval name = param.method.nameif (name != methodName) {Log.w(TAG, "afterHookedMethod: name is $name")return}printCommon(param, name, "after")}})}

这样当所有的 ViewGroup 调用 onInterceptTouchEvent 方法的时候,会回调相应的方法,其中

  • beforeHookedMethod 在方法回调前调用

  • afterHookedMethod 在方法执行后回调

当我们 hook 事件之后,当我们发生 move 事件,我们能够完整看到 move 事件的分发,从 ACTION_DOWN 到 ACTION_MOVE 再到 ACTION_UP,这样能够帮助我们快速定位问题。

image-20230919163803595

小结

这种自定义 hook 的应用场景其实非常多,在 debug 环境,比如自定义 hook 定位权限等,还有自定义 hook 定位异常问题等等,我们要学会举一反三

前两年的时候也有写过一篇类似的文章RxJava2 堆栈信息显示不全解决方案, 有兴趣的可以看看。

推荐阅读

【原理篇】WebView 实现嵌套滑动,丝滑般实现吸顶效果,完美兼容 X5 webview

RxJava2 堆栈信息显示不全解决方案

自定义 behavior - 完美仿 QQ 浏览器首页,美团商家详情页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/86096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】七大排序算法详解

目录 ♫什么是排序 ♪排序的概念 ♪排序的稳定性 ♪排序的分类 ♪常见的排序算法 ♫直接插入排序 ♪基本思想 ♪算法实现 ♪算法稳定性 ♪时间复杂度 ♪空间复杂度 ♫希尔排序 ♪基本思想 ♪算法实现 ♪算法稳定性 ♪时间复杂度 ♪空间复杂度 ♫直接选择排序 ♪基本思想 ♪算法…

【日常业务开发】Java实现异步编程

【日常业务开发】Java实现异步编程 Java实现异步编程什么是异步异步的八种实现方式异步编程线程异步Future异步CompletableFuture实现异步Spring的Async异步Spring ApplicationEvent事件实现异步消息队列ThreadUtil异步工具类Guava异步 CompletableFuture异步编排工具类创建异步…

unity自己对象池的使用

unity出了自己的对象池 这里记录一下用法 命名空间就是这个 一般有两种用法,第一种是在using里面获取,脱离这个域就释放。第二种是在Get和Release配合使用 // This version will only be returned to the pool if we call Release on it.//只有使用Re…

Android进阶之路 - 盈利、亏损金额格式化

在金融类型的app中,关于金额、数字都相对敏感和常见一些,在此仅记录我在金融行业期间学到的皮毛,如后续遇到新的场景也会加入该篇 该篇大多采用 Kotlin 扩展函数的方式进行记录,尽可能熟悉 Kotlin 基础知识 兄弟 Blog StringUti…

MediaPipe+OpenCV 实现实时手势识别(附Python源码)

MediaPipe官网:https://developers.google.com/mediapipe MediaPipe仓库:https://github.com/google/mediapipe 一、MediaPipe介绍 MediaPipe 是一个由 Google 开发的开源跨平台机器学习框架,用于构建视觉和感知应用程序。它提供了一系列预训…

Redis 面霸篇:从高频问题透视核心原理

Redis 为什么这么快? 很多人只知道是 K/V NoSQl 内存数据库,单线程……这都是没有全面理解 Redis 导致无法继续深问下去。 这个问题是基础摸底,我们可以从 Redis 不同数据类型底层的数据结构实现、完全基于内存、IO 多路复用网络模型、线程…

HTML5day02综合案例2

案例展示 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>注册信息</title> </head> &l…

新思路,4.9+氧化应激相关基因构建风险模型

今天给同学们分享一篇氧化应激预后模型的生信文章“Construction of an oxidative stress-related lncRNAs signature to predict prognosis and the immune response in gastric cancer”&#xff0c;这篇文章于2023年5月31日发表在Scientific Reports期刊上&#xff0c;影响因…

分库分表MySQL

目录 Mycat入门 分片配置 分片配置(配置Mycat的用户以及用户的权限) 启动服务 登录Mycat Mycat配置 schema.xml 1.schema标签:配置逻辑库,逻辑表的相关信息 1-1.核心属性 1-2.table标签 2.datanode标签:配置数据节点的相关信息 核心属性 3.datahost标签:配置的是节…

力扣 -- 215. 数组中的第K个最大元素

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int QuickSelectSort(vector<int>& nums,int begin,int end,int k){//随机选keyint keynums[beginrand()%(end-begin1)];//left在左端点前一个位置int leftbegin-1;//right在右端点后一个位置in…

【Verilog语法】比较不同计数器的运算方式,其中有一个数是延迟打一拍的效果,目的是使得两个计数器的结果相同。

比较不同计数器的运算方式&#xff0c;其中有一个数是延迟打一拍的效果&#xff0c;目的是使得两个计数器的结果相同。 1&#xff0c;第一种2&#xff0c;第二种3&#xff0c;第三种 第三种方案&#xff0c;完成实现。 1&#xff0c;第一种 &#xff08;1&#xff09;RTL modu…

【深度学习】图像去噪(2)——常见网络学习

【深度学习】图像去噪 是在 【深度学习】计算机视觉 系列文章的基础上&#xff0c;再次针对深度学习&#xff08;尤其是图像去噪方面&#xff09;的基础知识有更深入学习和巩固。 1 DnCNN 1.1 网络结构 1.1.1 残差学习 1.1.2 Batch Normalization (BN) 1.1.2.1 背景和目标…

如何使用固态硬盘+硬盘盒子+U盘创造移动双系统

本文背景 这学期上了一节鸟水课《大数据实践》&#xff0c;老师要求扩展硬盘盒&#xff0c;以部署大数据工具进行 机器挖掘等大数据领域工作 参考视频链接&#xff1a;无需启动盘&#xff0c;用虚拟机将ubuntu安装到移动硬盘上_哔哩哔哩_bilibili 项目使用设备 1.绿联&#…

软件工程之总体设计

总体设计是软件工程中的一个重要阶段&#xff0c;它关注整个系统的结构和组织&#xff0c;旨在将系统需求转化为可执行的软件解决方案。总体设计决定了系统的架构、模块划分、功能组织以及数据流和控制流等关键方面。 可行性研究 具体方面&#xff1a;经济可行性、技术可行性…

RabbitMQ的工作模式——WorkQueues

1.工作队列模式 生产者代码 public class Producer_WorkQueues1 {public static void main(String[] args) throws IOException, TimeoutException {//1.创建连接工厂ConnectionFactory factory new ConnectionFactory();//2.设置参数factory.setHost("172.16.98.133&qu…

81《乡村振兴战略下传统村落文化旅游设计》许少辉瑞博士生辉少许——2023学生开学季许多少年辉光三农

81《乡村振兴战略下传统村落文化旅游设计》许少辉瑞博士生辉少许——2023学生开学季许多少年辉光三农

ESD门禁闸机的用途及优点

ESD门禁闸机是一种专门用于防止静电干扰的门禁设备&#xff0c;其主要用途包括&#xff1a; 防止静电干扰&#xff1a;ESD门禁闸机可以有效地防止静电干扰&#xff0c;保护电子元器件、电路板等敏感设备不受静电破坏。 控制人员进出&#xff1a;ESD门禁闸机可以通过身份验证等…

AWS入列CNCF基金会

7月27日&#xff0c;IT之家曾经报道&#xff0c;微软加入Linux旗下CNCF基金会&#xff0c;在这之后不到一个月的今天&#xff0c;亚马逊AWS也宣布&#xff0c;以铂金身份加入此基金会。 CNCF&#xff0c;全称Cloud Native Computing Fundation&#xff0c;该基金会旨在使得容器…

Netty简介及简单客户端/服务端示例代码

什么是Netty&#xff1f; Netty是一个NIO客户机-服务器框架&#xff0c;它支持快速而容易地开发网络应用程序&#xff0c;如协议服务器和客户机。它大大简化和简化了网络编程&#xff0c;如TCP和UDP套接字服务器。 “快速简单”并不意味着生成的应用程序将遭受可维护性或性能问…

【再识C进阶3(上)】详细地认识字符串函数、进行模拟字符串函数以及拓展内容

小编在写这篇博客时&#xff0c;经过了九一八&#xff0c;回想起了祖国曾经的伤疤&#xff0c;勿忘国耻&#xff0c;振兴中华&#xff01;加油&#xff0c;逐梦少年&#xff01; 前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;…