Android从触碰屏幕开始的事件采集,解析及分发(1)
发布日期:2021-06-29 15:28:14 浏览次数:2 分类:技术文章

本文共 2660 字,大约阅读时间需要 8 分钟。

关于Android的事件分发机制,网上的文章快烂大街了, 大多数文章都是在千篇一律的讲activity, viewgroup, view之间的分发机制, 对于事件的源头却没有提及. 比如, 当手指触碰屏幕的一瞬间, 手机是怎么知道手指触碰的哪里, 是触碰的back键, 还是home键, 还是哪个坐标点, 是点击事件, 还是滑动事件等等, 也就是说, Android系统的事件采集是怎样的. 接下来是怎么把这些采集的事件信息进行处理的, 由谁来处理, 处理完成后又是由谁最后分发给到具体的activity的? 

有人可能会说, 作为一个普通的Android应用层开发者, 不需要掌握这些也可以啊, 我不想知道事件是怎么来的, 我只知道事件是怎么分发的, 我能够在程序中控制事件就可以了. 的确, 事实是这样, 不了解这些不影响应用层的开发, 但是如果掌握了这些, 那就太有意思了, 可以做很多有意思的事情,。

比如说, 按键精灵类的app为什么能够记忆你的操作, 而且还能够自动模拟你的操作而解放你的双手? 其实, 这类app的原理无非就是通过某个办法来采集到你的所有的操作过程, 即事件采集, 这样他就记忆下来了, 当需要自动模拟事件的时候, 它会把这些采集到的信息经过处理, 转变成可执行信息,这样就能够实现模拟人的双手来进行自动模拟操作了.

因为要想讲清楚整个事件的采集,处理及分发过程, 篇幅过大, 因此准备用一个系列文章来讲, 本文是系列文章的开篇, 那么先讲采集.


(一) 原始事件信息

打开模拟器, 或者用usb把手机连接上电脑并打开手机上面的开发者模式, (这里为了截图方便用了模拟器)打开cmd, 输入adb shell getevent回车, 然后点击模拟器或者手机后, 就会看到有N多行的/dev/input/event......输出. 其实, 这些信息就是最原始的事件信息.

(注:严格来说最原始的信息肯定是由硬件捕获到的, 这里所说的原始信息是经过硬件处理后返回给framework层的信息)

640?wx_fmt=gif

再看一下, 我们能否通过cmd命令来控制手机来模拟操作事件呢? 重新打开cmd, 或者Ctrl + c退出刚才的命令, 重新执行adb shell input keyevent 4 , 发现手机自动执行了返回键

640?wx_fmt=gif

(二) 信息分析

以上简单的演示了下采集信息和发送信息, 接下来开始解析信息.cmd重新执行adb shell getevent -t -l, 再次点击手机的某个app, 显示出的信息是这样的: 

640?wx_fmt=png

前面[   13236.364793]显示的是时间, 是手机或模拟器开机后到命令执行时的时间间隔, 后面显示的是具体命令, 其中, /dev/input/event1表示的是屏幕的输入事件,  第一个ABS_MT_TRACKING_ID 表示采集信息开始, 后一个ABS_MT_TRACKING_ID表示采集信息结束,  ABS_MT_PRESSURE表示的是屏幕感受到的压力值, SYN_REPORT 表示的是同步数据, 最重要的是ABS_MT_POSITION_X和ABS_MT_POSITION_Y, 毫无疑问, 这个就是表示屏幕感受到的触碰坐标位置. 最右边的一列是16进制的值. 

其他的信息我们可以先忽略, 最主要的是要记录时间和坐标点, 接下来就是把采集到的坐标点转换成10进制的坐标点, x坐标采集到的值是00005487,转换10进制是21639, 同理, y坐标转换前是00006b5b, 转换后是27483,  接下来需要根据公式来获取到真正的应用层能识别的坐标系, 具体公式为:

x = (x-xmin) * 手机像素宽 / (xmax-xmin) ;	y = (y-ymin) * 手机像素高 / (ymax-ymin);

手机像素我们可以通过代码获取当前手机的像素, 但是xmin和xmax, 以及ymin和ymax是什么呢?我们还是通过cmd用adb shell getevent -p命令来获取. 执行命令后,拉到最下方, 看到如下图示:

640?wx_fmt=png

我们找到0035和0036的行, 即

0035  : value 0, min 0, max 32767, fuzz 0, flat 0, resolution 0	0036  : value 0, min 0, max 32767, fuzz 0, flat 0, resolution 0

0035所在的行就是x信息, 0036所在的行就是y信息, 每行的min值和max值对应上面公式的min和max, 所以我这里最终转换成的x, y坐标结果如下: (我的模拟器经过代码获取的宽高分辨率分别是480, 728)

x = (21639 - 0) * 480 / (32767 - 0) = 317	y = (27483 - 0) * 728 / (32767 - 0) = 610

即当点击手机桌面屏幕的(317, 610)坐标, 就打开了这个app, 那么我们接下来验证一下, 通过cmd来发送命令, 来模拟点击事件, 看看模拟器或者手机是不是能打开这个app呢?

重新打开cmd, 执行adb shell input tap 317 610命令, 结果如下:

640?wx_fmt=gif

我们成功的通过命令来模拟点击桌面应用了. 其实整个过程就是一个采集信息,处理信息,发送信息的过程。


到这里,我们其实就可以自己开发出来一个简单版的类似按键精灵类的app了,大体思路就是在app中给一个按钮,用来触发采集信息,之后用户的一切触屏行为都将进行录入。再给一个结束采集的按钮,当触发时停止事件采集并且进行信息的处理,包括事件的属性,比如是点击事件还是滑动事件,点击或滑动的起始坐标,以及相邻两个事件的时间间隔等等,最后保存起来。最后再给一个开始模拟事件的按钮,用来执行处理过的事件信息,当触发时,程序就会自动执行模拟事件了。

以上,是我们人为的进行事件的采集和处理,那么Android系统内部又是怎么做的呢?是谁负责把事件信息处理后转换成为各种KeyEvent或者MotionEvent的,以及最终是怎么传递到的activity中的呢?我们下回分解。

用手机预览了下动图效果感觉不是很好,可以用电脑访问https://www.jianshu.com/p/6c5d665b8f2e,或者点击阅读原文,动图会看的更清楚。

如果觉得写的还不错,请关注我的公众号:

640?wx_fmt=jpeg

转载地址:https://codegg.blog.csdn.net/article/details/91454983 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:福利来袭,免费获取 Android 开发资料以及直播课程
下一篇:android Superuser.apk源码分析

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月24日 01时21分36秒