打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android模拟产生事件

我们有时候需要使用程序产生一些输入事件。例如一些“丧心病狂”的App,让你发疯的狂点屏幕来抽奖,程序来帮你,包你中奖。当然,本文并不是为了来作弊,而是开发过程中的一些实用工具。

给系统模拟注入输入事件有如下几种方式:

1. 使用shell命令

Android中自带一个input工具,使用方法如下:

 adb shell #进入系统

输入如下命令:

 input keyevent KEYCODE_BACK 或者 input keyevent 3  #模拟按返回键 input keyevent KEYCODE_HOME  #模拟按Home键

上面的命令就给Android系统输入了相应的按键,使用方法是input keyevent <按键名或者按键值>。按键名或者值可以从官方文档查询,只要是以KEYCODE_开头的都可以。

如果系统的焦点在输入框内,还可以直接输入文本:

 input text hello

直接在输入框内输入hello。输入的文本不能带空格,也不能是中文,真是很遗憾。

还可以直接输入点击屏幕的事件,模拟点击屏幕

input tap 100 200  #在屏幕坐标(100, 200)处点击  

使用方法是input tap <x> <y>。坐标从屏幕左上角开始算。也可以模拟长按,滑动等等,详细的用法如下:

Usage: input [<source>] <command> [<arg>...]The sources are:        trackball      joystick      touchnavigation      mouse      keyboard      gamepad      touchpad      dpad      stylus      touchscreenThe commands and default sources are:        text <string> (Default: touchscreen)      keyevent [--longpress] <key code number or name> ... (Default: keyboard)      tap <x> <y> (Default: touchscreen)      swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)      press (Default: trackball)      roll <dx> <dy> (Default: trackball)      tmode <tmode>

2. 使用Instrumentation

Instrumentation本身是Android用来做测试的工具,可以通过它监测系统与应用程序之间的交互。详情可以参考官方文档Android测试。我们这里只关注怎么使用Instrumentation产生发送按键或者触屏事件。

发送按键:

Instrumentation mInst = new Instrumentation();  mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_CAMERA);  

sendKeyDownUpSync()从名字上就能看出,这是同步发送一个按键按下和弹起事件。

发送触屏事件:

Instrumentation mInst = new Instrumentation();  mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),      SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0);mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),      SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);

同样,sendPointerSync()是同步发送发送触摸事件。

与Shell工具一样,还有类似sendStringSync()发送文本,sendTrackballEventSync()发送轨迹球事件等方法。

注意,使用上面的方法,在AndroidManifast.xml中申明如下权限:

<uses-permission android:name="android.permission.INJECT_EVENTS"/>  

遗憾的是android.permission.INJECT_EVENTS是一个System权限,折腾起来有点麻烦,可以参考这里

3. 使用Android内部API

在Android系统中,有些内部的API提供注入事件的方法。因为是内部API,在不同版本上可能变化比较大。使用如果想在普通App中使用,可能需要通过反射机制来调用。

在Android API 16之前,WindownManager有相应的方法提供注入事件的方法,如下:

IBinder wmbinder = ServiceManager.getService("window");  IWindowManager wm = IWindowManager.Stub.asInterface(wmbinder); //pointer  wm.injectPointerEvent(myMotionEvent, false); //key  wm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A), false);  wm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A), false); //trackball  wm.injectTrackballEvent(myMotionEvent, false);  

在API 15之后,引入了InputManager,把上面的哪些injectXXXEvent()方法从WindowManager中移除了。使用方法类似:

IBinder imBinder = ServiceManager.getService("input");  IInputManager im = IInputManager.Stub.asInterface(imBinder);//inject key eventfinal KeyEvent keyEvent = new KeyEvent(downTime, eventTime, action,      code, repeatCount, metaState, deviceId, scancode,     flags | KeyEvent.FLAG_FROM_SYSTEM |KeyEvent.FLAG_KEEP_TOUCH_MODE | KeyEvent.FLAG_SOFT_KEYBOARD,     source);event.setSource(InputDevice.SOURCE_ANY)  im.injectInputEvent(keyEvent, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);//inject pointer eventmotionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);  im.injectInputEvent(motionEvent, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);  

从API 16开始,InputManager就成了一个公开的类了,可以通过如下方法获得InputManager实例:

InputManager im = (InputManager) getSystemService(Context.INPUT_SERVICE);  

注意,使用injectEvent()同样需要申明android:name="android.permission.INJECT_EVENTS"权限。

4. 使用Nativ/JNI调用

察看Android设备的/dev/input/目录下的设备:

shell@mako:/dev/input $ ll  crw-rw---- root     input     13,  64 2013-08-11 18:00 event0  crw-rw---- root     input     13,  65 2013-08-11 18:00 event1  crw-rw---- root     input     13,  66 2013-08-11 18:00 event2  crw-rw---- root     input     13,  67 2013-08-11 18:00 event3  crw-rw---- root     input     13,  68 2013-08-11 18:00 event4  crw-rw---- root     input     13,  69 2013-08-11 18:00 event5  

可以看到有一些输入设备节点,同时也提供了一些shell工具来操作这些设备,例如上面第1节中提到的input命令,另外还有geteventsendevent工具分别来监听和发送事件。这些方法,都可以通过JNI的方式调用。这里需要注意的时间eventX设备都是input的用户组,要直接使用,需要root设备。

特别的是,这里有一个开源项目android-event-injector,使用JNI方法注入事件。当然设备需要root。

参考文章:1 http://blog.djodjo.org/?p=628
2 http://www.pocketmagic.net/2012/04/injecting-events-programatically-on-android/#.VKn42M2UfCI

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android 2.3 input输入事件处理
Android代码模拟物理、屏幕点击事件 、APP内部自动点击
android 事件处理(三)
android 键盘事件和屏幕事件的运行原理及交互实现
android 键值控制显示屏 TP调试
Android用户输入系统结构和移植内容
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服