做视频背景音乐网站,北京市建设工程信息网告知性备案,域名交易网站源代码下载,vi设计的基本要素转载请注明出处 早想写这篇#xff0c;一直没空#xff0c;现在总结下。 需求#xff1a; 需要在程序内模拟用户输入#xff0c;比如点击屏幕#xff0c;或者输入键盘。模拟用户的滑动等。具体的需求#xff0c;比如测试的时候#xff0c;测试打开浏览器1000次。或者通过… 转载请注明出处 早想写这篇一直没空现在总结下。 需求 需要在程序内模拟用户输入比如点击屏幕或者输入键盘。模拟用户的滑动等。具体的需求比如测试的时候测试打开浏览器1000次。或者通过网络发送命令给手机在手机上执行点击或者输入。再或者平板和蓝牙鼠标通过蓝牙通信通过鼠标让平板上的鼠标能移动和点击。这些都需要用到事件注入。 分析 模拟用户输入的方式有几种一是monkeyrunner这个的原理是在PC上通过python调用android的一些包然后通过机器的调试端口和机器通信机器接收到相应的命令后再往硬件写入相应的事件。这个常用语测试。并且不是所有的机器都开了调试端口并且需要连接PC。二是IwindowManager的injectInputEventNoWait这个调用方便也很简单但是从1.5(1.6?)后android系统做了限制不允许跨进程注入这个方法只能在自己这个程序内用home出去就不行了。三是直接往linux底层/dev/input/event*写事件这个实现起来复杂需要root权限但是却能实现跨进程比如蓝牙鼠标的需求也只能用这种方法实现。讲这个具体实现的不多本文详细介绍下。对linux了解些的人应该一看就懂知道怎么回事。android上实现只不过有些地方比较绕而已。 1.android界面点击事件流程。 有必要先说下android界面捕获事件的流程。用户在屏幕上点击一下后程序里面的OnClickListener是怎样收到这个事件的。大致流程如下 用户点击-(硬件驱动部分)硬件产生一个中断往/dev/input/event*写入一个相应的信号-gt;jni部分android循环读取/dev/input/event*的事件再分发给WindowManagerServer最后再发到相应的ViewGroup和View。这里可以通过往/dev/input/event*写信号的方式来达到模拟事件的目的接下来关心的就是信号的协议了。 2.按键协议分析 连接手机adb shell输入getevent关掉手机的自动旋转屏幕按一下手机的menu键会看到类似如下输出。 linux上的硬件会分别对应/dev/input/event*,这里的*一般是0-9的数字getevent开头那部分已经显示event2是keypad,event1是touchscreen等。 最下面的0001 008b 00000001分别叫做type,code,value。 参考linux input,type 对应 【#define EV_KEY 0x01】,code 对应【#define KEY_MENU 139】(8b 139),value 1表示按下0表示松开。那么按键的协议就很清楚了试着在adb shell里面输入“sendevent /dev/input/event2 0 139 1”和”sendevent /dev/input/event2 0 139 2“后发现menu弹出来了和按键的效果一样。 3.触摸协议分析 ok来点复杂的。触摸协议稍微麻烦点分单点触摸和多点触摸。 先说单点触摸打开模拟器。同样关闭自动旋屏进入adb shell。鼠标点击一下屏幕要足够快不然数据太多。得到输出和下面类似。 可以看到模拟器上的设备数少了很多单点触摸的协议每次点击会写6条信号。参考linux_input对应的值以及分析分别如下 /dev/input/event0: 0003 0000 00000117 EV_ABS ABS_X 0x117 触摸点的x坐标 /dev/input/event0: 0003 0001 0000020f EV_ABS ABS_Y 0x20f 触摸点的y坐标 /dev/input/event0: 0001 014a 00000001 EV_KEY BTN_TOUCH 1 touch down /dev/input/event0: 0000 0000 00000000 EV_SYN 0 0 同步信号量 /dev/input/event0: 0001 014a 00000000 EV_KEY BTN_TOUCH 0 touch up /dev/input/event0: 0000 0000 00000000 EV_SYN 0 0 同步信号量 使用4.0的模拟器settings-developer options-show touches 和pointer locations勾上后可以看到点击的轨迹adb shell后分别用sendevent输入以上消息可以看到屏幕上出现点击效果。 再看多点触摸协议使用adb shell 进入手机关掉旋屏getevent后快速点一下屏幕可以看到类似如下输出。(每个厂商的协议可能不同以下数据为小米1的) 第一个坐标 /dev/input/event1: 0003 0039 00000000 EV_ABS ABS_MT_TRACKING_ID 0 /dev/input/event1: 0003 0035 000001b0 EV_ABS ABS_MT_POSITION_X 0x1b0 /dev/input/event1: 0003 0036 000000d7 EV_ABS ABS_MT_POSITION_Y 0xd7 /dev/input/event1: 0003 003a 00000001 EV_ABS ABS_MT_PRESSURE 0x1 /dev/input/event1: 0003 0032 00000001 EV_ABS ABS_MT_WIDTH_MAJOR 0x1 /dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0 /dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0 第二个坐标 /dev/input/event1: 0003 0039 00000000 EV_ABS ABS_MT_TRACKING_ID 0 /dev/input/event1: 0003 0035 000001b0 EV_ABS ABS_MT_POSITION_X 0x1b0 /dev/input/event1: 0003 0036 000000d7 EV_ABS ABS_MT_POSITION_Y 0xd7 /dev/input/event1: 0003 003a 00000001 EV_ABS ABS_MT_PRESSURE 0x1 /dev/input/event1: 0003 0032 00000001 EV_ABS ABS_MT_WIDTH_MAJOR 0x1 /dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0 /dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0 第三个坐标 /dev/input/event1: 0003 0039 00000000 EV_ABS ABS_MT_TRACKING_ID 0 /dev/input/event1: 0003 0035 00000191 EV_ABS ABS_MT_POSITION_X 0x191 /dev/input/event1: 0003 0036 00000098 EV_ABS ABS_MT_POSITION_Y 0x98 /dev/input/event1: 0003 003a 00000001 EV_ABS ABS_MT_PRESSURE 0x1 /dev/input/event1: 0003 0032 00000001 EV_ABS ABS_MT_WIDTH_MAJOR 0x1 /dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0 /dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0 松开 /dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0 /dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0 这里是一次点击注意到ABS_MT_TRACKING_ID都是一样的。系统检测到三个点每次会发送点的x,y,以及收到的压力触摸的范围。最后两条表示松开这个点。如果两个手指同时点击可以发现ABS_MT_TRACKING_ID会有两个不同的值分别是两个点。据说最多支持5点。 每个厂商实现协议不一样。htc g3如下 /dev/input/event1: 0003 003a 002a0002 /dev/input/event1: 0003 0039 8b8c0ddc /dev/input/event1: 0003 003a 00000002 /dev/input/event1: 0003 0039 8bac0dde /dev/input/event1: 0003 003a 00000000 /dev/input/event1: 0003 0039 802814b1 4.可能遇到的问题 实际实现的时候还可能遇到问题 一是rootgetevent和sendevent需要/dev/input/event*的权限。一般应用是没有这个权限的需要在程序里面获取su后执行chmod 666 /dev/input/event*。 二是设备名称。因为你不知道触摸屏或者按键到底对应的event*是多少。需要有一个初始化的过程大致思路是往event0-event9分别写入按键和触摸信号同时监听activity里的onkeydown和view的onclick这样来侦测设备。 三是厂商的实现不一样这个没办法只能一个一个适配了一般来说都还是标准的有些厂商会有单独的实现。 参考 http://lxr.free-electrons.com/source/include/uapi/linux/input.h#L803 http://source.android.com/tech/input/touch-devices.html http://cjix.info/blog/misc/internal-input-event-handling-in-the-linux-kernel-and-the-android-userspace/