尊重原创转载请注明: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 : /dev/input/event0
name: "mxhub-keys"
add device : /dev/input/event4
name: "lsm330dlc_gyr"
add device : /dev/input/event3
name: "lsm330dlc_acc"
add device : /dev/input/event1
name: "gp2ap"
could not get driver version for /dev/input/mouse0, Not a typewriter
add device : /dev/input/event5
name: "mx_ts"
add device : /dev/input/event6
name: "gpio-keys"
add device : /dev/input/event7
name: "Headset"
add device : /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 上报接触面的中心点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 上报主接触面长轴
/dev/input/event5: EV_SYN SYN_REPORT 同步数据
/dev/input/event5: EV_ABS ABS_MT_PRESSURE
上报手指压力
/dev/input/event5: EV_ABS ABS_MT_TOUCH_MAJOR
上报主接触面长轴
/dev/input/event5: EV_SYN SYN_REPORT 同步数据
/dev/input/event5: EV_ABS ABS_MT_TRACKING_ID ffffffff
标志多点追踪信息的采集结束(需要设备支持)
/dev/input/event5: EV_SYN SYN_REPORT 同步数据

如上过程只是一次快速触碰所产生的节点读取,如果我们做出更复杂的手势操作比如多点切西瓜那样的效果尼玛光是采集这些信息都不得了!不过值得庆幸的是,对这些原始信息的采集用不着应用层的开发者来做,对于应用开发来说我们往往更关心一次事件是单击呢还是双击还是长按等等,而不是面对这些庞大而又复杂的原始信息,So,Android在获取到这些原始数据后会对其进行一定的转化便于使用,当然如果你需要做驱动开发涉及到这些原始数据的操作也可以直接获取其使用亦可。

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

(转)使用getevent监听Android输入设备文件的更多相关文章

  1. 监听Android CTS测试项解决方案(一)

    前言: 首先这里需要详细叙述一下标题中"监听Android CTS测试项解决方案"的需求.这里的需求是指我们需要精确的监听到当前CTS测试正在测试的测试项. 因为我们知道CTS认证 ...

  2. vue 定义全局函数,监听android返回键事件

    vue 定义全局函数,监听android返回键事件 方法一:main.js 注入(1)在main.js中写入函数Vue.prototype.changeData = function (){ aler ...

  3. 监听Android CTS测试项解决方案(二)

    二,监听当前测试项是否是Accelerometer Measurement Test测试项 通过第一种方式介绍的,我们可以得到当前处于活动状态的Activity类似监听CTS测试当前的测试项.但是由于 ...

  4. Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

    本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.c ...

  5. 【Android代码片段之八】监听Android屏幕是否锁屏

    实现方法:1)通过BroadcastReceiver接收广播Intent.ACTION_SCREEN_ON和Intent.ACTION_SCREEN_OFF可以判断屏幕状态是否锁屏,但是只有屏幕状态发 ...

  6. 从网页监听Android设备的返回键

    最近搞Android项目的时候,遇到一个比较蛋疼的需求,需要从Client App调用系统浏览器打开一个页面,进行杂七杂八的一些交互之后,返回到App.如何打开浏览器和如何返回App这里就不说了,有兴 ...

  7. Android开发——监听Android手机的网络状态

    0. 前言 在Android开发中监听手机的网络状态是一个常见的功能,比如在没网的状态下进行提醒并引导用户打开网络设置,或者在非wifi状态下开启无图模式等等.因此本篇将网上的资料进行了整理总结,方便 ...

  8. 文件和文件夹不存在的时候,FileSystemWatcher 监听不到文件的改变?如果递归地监听就可以了

    当你需要监视文件或文件夹的改变的时候,使用 FileSystemWatcher 便可以完成.不过,FileSystemWatcher 对文件夹的监视要求文件夹必须存在,否则会产生错误“无效路径”. 那 ...

  9. 让webStorm支持自动监听编译scss文件

    前提概要 今日,重装了两波系统,,,之前安装的各种环境都忘光了,重新又踩一次坑的感觉很不舒服,所以记录一下配置自动编译scss一路遇到的坑 一.webstrom run的时候控制台输出的错误中文提示乱 ...

随机推荐

  1. 【Android 界面效果35】管理Fragments

    http://www.cnblogs.com/mengdd/archive/2013/01/09/2853254.html

  2. Unity3d之Shader编程:子着色器、通道与标签的写法 & 纹理混合

    一.子着色器 Unity中的每一个着色器都包含一个subshader的列表,当Unity需要显示一个网格时,它能发现使用的着色器,并提取第一个能运行在当前用户的显示卡上的子着色器. 我们知道,子着色器 ...

  3. GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树

    GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...

  4. loadrunner协议的选择

    1. 任何高级协议的底层都是用Winsocket通信   2. 不管你系统中有多少个服务器,lr录制的始终是客户端与第一个服务器之间的通信内容, 客户端用IE访问的一般都选http协议(对于常见的,b ...

  5. Table of Contents - Jersey

    Jersey 1.19.1 Getting Started Get started with Jersey using the embedded Grizzly server Get started ...

  6. 基于ASP.Net +easyUI框架上传图片,实现图片上传,提交表单

    <body> <link href="../../Easyui/themes/easyui.css" rel="stylesheet" typ ...

  7. Android里viewpager切换页面存在页面不相邻的页面被销毁的问题

    我之前一直因为viewpager+fragment时,所有页面的状态都会被自动保存 这次自己做了一个添加了5跟fragment的viewpager 测试时发现当从第一个切换到第四个页面时,再回到第一个 ...

  8. 简单的MySQL数据库主从同步配置

    Master配置: 代码如下 复制代码 log-bin = mysql-binserver-id = 1binlog-do-db = powerdns #要同步的数据库 Master新增slave账号 ...

  9. 20141104--SQL连接查询,联合查询

    ---------------------------连接查询-------------------------------- --横向连接查询 --可以将子查询放在from之前,用来替换显示出来的信 ...

  10. 分享8款最新HTML5/CSS3功能插件及源码下载

    1.HTML5/CSS3鬼脸表情下拉菜单 超级可爱 这款HTML5/CSS3鬼脸表情下拉菜单真的很特别,虽然菜单的实现并没有利用复杂的HTML5/CSS3技术,但是创意的确不错. 在线演示 源码下载 ...