Android事件分发完全解析之事件从何而来

原创 2015年03月30日 09:55:01

尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究!

炮兵镇楼

上一节Android事件分发完全解析之为什么是她中我们简略地分析了事件分发机制的由来,这里要说明一点,Android(或者说任何的驱动系统)都包含大量不同类型的事件,比如按键啦、轨迹球啦、鼠标啦、触摸啦、红外线啦等等等,这里为了简化问题也为了切合实际,我们只针对触摸事件进行分析,至于其他的一些杂七杂八的事件其实都很好理解就不多说了。

那么在Android中一个触摸事件究竟是从何而来的呢?对事件分发稍有了解的童鞋一定知道dispatchtouchevent方法,都知道View对触摸事件进行分发的起点,但是传入dispatchtouchevent方法中的触摸事件又是从何而来的呢?往上一步步追踪你会发现代码调用无穷无尽找不到头……有时候盲目地去read fuck source code反而会让你更困惑,其实用脑子想想理清逻辑就可以很快找到答案,我们都知道一个事件的产生肯定需要用户的交互,也就是说,只有当用户触摸屏幕或按下某个按键之类的操作之后系统才能做出事件响应,而每一个这样的操作我们都可将其当作事件的“源头”,那么捕获这些最原始交互信息的猎手应该是谁呢?还会是View?还会是Activity?还会是ViewRootImpl还会是WMS吗?这些framework中的构件相对于更底层的机制来说还是太“高级”了,我们知道Android是基于Linux的一款操作系统,Linux其本身就有一个很Perfect的Input子系统架构,Android虽然也实现了几个属于自己的机制,但是大部分底层的调用还是基于Linux所提供的操作接口,比如对Input驱动的编写就是基于Linux Input系统字符驱动的操作接口,关于Linux的这部分大家如果有兴趣可以去看看私房菜,这里就不多扯了,这里你仅需要知道在Android中Linux的Input子系统会在/dev/input/路径下读写以event[NUMBER]为名的硬件输入设备节点。这些节点都是跟具体硬件有关的,所以呢可能每一款设备的具体节点名都是不一样的,比如在我的mx3中/dev/input/event0为mxhub-key而/dev/input/event1为gp2ap。具体的节点信息可通过Android提供的getevent工具查看,如果你的设备已经连接了PC或者模拟器已启动,adb shell后getevent即可获取事件读写的实时状态,当然各个设备是不一样的,比如mx3中通过getevent查看所有Input节点:

Aigestudio>adb shell
shell@mx3:/ $ getevent
getevent
add device 1: /dev/input/event0
  name:     "mxhub-keys"
add device 2: /dev/input/event4
  name:     "lsm330dlc_gyr"
add device 3: /dev/input/event3
  name:     "lsm330dlc_acc"
add device 4: /dev/input/event1
  name:     "gp2ap"
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 5: /dev/input/event5
  name:     "mx_ts"
add device 6: /dev/input/event6
  name:     "gpio-keys"
add device 7: /dev/input/event7
  name:     "Headset"
add device 8: /dev/input/event2
  name:     "compass"
could not get driver version for /dev/input/mice, Not a typewriter
可见mx3中有8个Input子系统,分别为:

  • 位于event0节点下读写魅族呼吸灯按钮也就是屏幕下方圆形的那个发光主键的“mxhub-keys”子系统
  • 位于event4节点下读写重力传感器的“lsm330dlc_gyr”子系统
  • 位于event3节点下读写加速度传感器的“lsm330dlc_acc”子系统
  • 位于event1节点下读写红外线传感器的“gp2ap”子系统(魅族mx3是用红外线来测定光感和距离的)
  • 位于event5节点下读写屏幕触摸的“mx_ts”子系统
  • 位于event6节点下读写物理按键的“gpio-keys”子系统
  • 位于event7节点下读写耳机按键的“Headset”子系统(有些手机监控线控设备的系统常以hook为名,这里魅族使用不多见Headset来表示该类不知是否是有布局头戴式设备的意义)
  • 位于event2节点下读写罗盘的“compass”子系统

而mx3(不能说是Android哈这里针对mx3)就是从这些系统节点中读写设备的事件信息,以上信息我是在mx3灭屏时也就是按下电源键关闭屏幕后获取的,如果我们再次按下电源点亮屏幕,内核驱动就会不断地监控一些必要的读写事件,这里我们不想让我们的Terminal一直输出,使用getevent的-c参数设定最大的输出条数查看即可:


这里我设定了最大16条输出,亮屏后可见如上信息显示,如果不作输出限制,Terminal就会一直输出……也就是说加速度和红外线传感器的子系统会不断检测外部环境的变化,至于为什么,想想加速度感应和红外感应我想大家都应该能心知肚明。如果我们在getevent后在屏幕上快速Touch一下,那么event5节点下的子系统就回立即作出回应:

如上图中我们快速接触屏幕后得到的信息,可能不好懂对吧,给getevent加上-l参数格式化输出看看:


注:因为硬件设备、触摸区域力度、持续时间等因素的影响你的输出结果可能跟我不大一样,以具体你具体的输出为准,但输出信息大致是类似的。

这里拿第一条信息“/dev/input/event5: EV_ABS       ABS_MT_TRACKING_ID   000008e0”来说,其中/dev/input/event5上面我们说了表示设备节点;EV_ABS表示type事件类型;ABS_MT_TRACKING_ID表示code事件的扫描码;000008e0则表示具体的事件值。这些信息的定义都在kernel/include/linux/input.h文件中作出了声明,比如type输入设备类型包括如下这些:

#define EV_SYN                  0x00
#define EV_KEY                  0x01
#define EV_REL                  0x02
#define EV_ABS                  0x03
#define EV_MSC                  0x04
#define EV_LED                  0x11
#define EV_SND                  0x12
#define EV_REP                  0x14
#define EV_FF                   0x15
#define EV_PWR                  0x16
#define EV_FF_STATUS            0x17
#define EV_MAX                  0x1f
具体它们都代表什么就不多说了,都是些Linux的东西,一般来说比较常用的是EV_REL表示相对坐标类型、EV_ABS表示绝对坐标类型、EV_KEY表示物理键盘事件类型,EV_SYN表示同步事件类型等等,一个设备可以支持多个不同的事件类型而每个事件类型呢又可以设置不同的事件码,比如EV_SYN同步事件类型的事件码如下:

#define SYN_REPORT      0  
#define SYN_CONFIG      1  
#define SYN_MT_REPORT       2  
其它的就不一一列举了都可以在input.h文件中找到相应的定义。上面图例中的一次快速触屏后的反馈信息可以做如下描述:

/dev/input/event5: EV_ABS       ABS_MT_TRACKING_ID   000008e0 标志多点追踪信息的采集开始(需要设备支持)
/dev/input/event5: EV_ABS       ABS_MT_POSITION_X    00000280 上报接触面的中心点X坐标
/dev/input/event5: EV_ABS       ABS_MT_POSITION_Y    0000064b 上报接触面的中心点Y坐标
/dev/input/event5: EV_ABS       ABS_MT_PRESSURE      0000005b 上报手指压力
/dev/input/event5: EV_ABS       ABS_MT_TOUCH_MAJOR   00000014 上报主接触面长轴
/dev/input/event5: EV_SYN       SYN_REPORT           00000000 同步数据
/dev/input/event5: EV_ABS       ABS_MT_PRESSURE      00000057
上报手指压力
/dev/input/event5: EV_ABS       ABS_MT_TOUCH_MAJOR   00000012
上报主接触面长轴
/dev/input/event5: EV_SYN       SYN_REPORT           00000000 同步数据
/dev/input/event5: EV_ABS       ABS_MT_TRACKING_ID   ffffffff
标志多点追踪信息的采集结束(需要设备支持)
/dev/input/event5: EV_SYN       SYN_REPORT           00000000 同步数据
如上过程只是一次快速触碰所产生的节点读取,如果我们做出更复杂的手势操作比如多点切西瓜那样的效果尼玛光是采集这些信息都不得了!不过值得庆幸的是,对这些原始信息的采集用不着应用层的开发者来做,对于应用开发来说我们往往更关心一次事件是单击呢还是双击还是长按等等,而不是面对这些庞大而又复杂的原始信息,So,Android在获取到这些原始数据后会对其进行一定的转化便于使用,当然如果你需要做驱动开发涉及到这些原始数据的操作也可以直接获取其使用亦可。

可见,Linux中Input子系统对输入设备信息的捕获可以说是Android事件来源的老祖宗,当然这些玩意对于应用开发者来说没必要深入理解,仅作了解即可。文章开头我们曾这样说过,一次事件的源头必定来自于用户的交互,那么事实上是不是如此呢?早年打过游戏的童鞋肯定对按键精灵这玩意很熟悉吧,至少不陌生,我们使用按键精灵来模拟用户对键位的操作,也就是说我们并不一定需要用户真实的交互,模拟也行。同样地Android也给我们提供了另外一个很酷的工具sendevent来向/dev/input/写入事件信息模拟事件的产生,具体用法跟getevent很类似,就不多说了,自行尝试。

Android开发中的事件分发机制梳理

本文为事件分发的学习总结。 《Android开发艺术探索》一书中对事件分发做了很详细的介绍。 大神博客:http://blog.csdn.net/singwhatiwannaView的事件分发机制...
  • android_zyf
  • android_zyf
  • 2017年03月05日 12:55
  • 614

Android触摸屏事件派发机制详解与源码分析三(Activity篇)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN。因为CSDN也支持MarkDown语法了,牛逼啊!【工匠若水 http://blog.csdn.net/yanbobe...
  • yanbober
  • yanbober
  • 2015年05月23日 12:56
  • 16990

Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

记得在前面的文章中,我带大家一起从源码的角度分析了Android中View的事件分发机制,相信阅读过的朋友对View的事件分发已经有比较深刻的理解了。 还未阅读过的朋友,请先参考 Android事件分...
  • sinyu890807
  • sinyu890807
  • 2013年07月05日 08:26
  • 102741

Android事件分发机制详解:史上最全面、最易懂

前言 Android事件分发机制是每个Android开发者必须了解的基础知识 网上有大量关于Android事件分发机制的文章,但存在一些问题:内容不全、思路不清晰、无源码分析、简单问题复杂化等等 今天...
  • carson_ho
  • carson_ho
  • 2017年01月06日 11:43
  • 35746

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

其实我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客开始,就零零散散在好多地方使用到了Android事件分发的知识。也有好多朋友问过我各种问题,比如:onTouch和onTouc...
  • sinyu890807
  • sinyu890807
  • 2013年06月20日 08:30
  • 319154

Android事件分发完全解析之事件从何而来

尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 上一节Android事...
  • qq_27073205
  • qq_27073205
  • 2015年05月28日 19:32
  • 271

Android事件分发机制完全解析,带你从源码的角度彻底理解

  • 2015年05月11日 11:55
  • 1.62MB
  • 下载

完全理解android事件分发机制

  • 2017年01月12日 09:10
  • 21.19MB
  • 下载

android 事件分发机制完全解析 从源码开始(下)

必须感谢郭林大侠为我们这些初入IT的菜鸟们提供了这么详尽的解析文章,本文是转载他的博文,主要是关于ViewGroup的事件分发,为了方便自己使用才转载过来,大家可到郭大侠的原博里面查看,下面附上原文链...
  • Kusonprince
  • Kusonprince
  • 2015年01月15日 15:22
  • 332

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

转载:http://blog.csdn.net/guolin_blog/article/details/9097463
  • ZBJDSBJ
  • ZBJDSBJ
  • 2014年12月03日 20:49
  • 891
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android事件分发完全解析之事件从何而来
举报原因:
原因补充:

(最多只允许输入30个字)