标签:monkey injectevent instrumentation
原文:http://www.pocketmagic.net/2012/04/injecting-events-programatically-on-android/#.VEoIoIuUcaV
往下分析monkey事件注入源码之前先了解下在android系统下事件注入的方式,翻译一篇国外文章如下。
该方法和其他所有内部没有向外正式公布的APIs一样存在它自己的风险。
The idea is to get an instance of WindowManager in order to access the injectKeyEvent / injectPointerEvent methods.
原理是通过获得WindowManager的一个实例来访问injectKeyEvent/injectPointerEvent这两个事件注入方法。
IBinder wmbinder = ServiceManager.getService( "window" ); IWindowManager m_WndManager = IWindowManager.Stub.asInterface( wmbinder );The ServiceManager and WindowsManager are defined as Stubs. We can then bind to these services and call the methods we need.
ServiceManager和Windowsmanager被定义为存根Stubs类。我们根据我们的需要绑定上这些服务并访问里面的方法。
To send a key do the following:
通过以下方式发送一个事件:
// key down m_WndManager.injectKeyEvent( new KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A ),true ); // key up m_WndManager.injectKeyEvent( new KeyEvent( KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A ),true );To send touch/mouse events use:
//pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHT m_WndManager.injectPointerEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,pozx, pozy, 0), true); m_WndManager.injectPointerEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,pozx, pozy, 0), true);This works fine, but only inside your application
这种方法能在你的应用中很好的工作,但,也仅仅只能在你的应用中而已
The moment you‘re trying to inject keys/touch events to any other window, you‘ll get a force close because of the following exception:
一旦你想要往其他窗口注入keys/touch事件,你将会得到一个强制关闭的消息:
E/AndroidRuntime(4908): java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permissionNot much joy, as INJECT_EVENTS is a system permission. A possible solution is discussed here and here.
苦逼了吧,毕竟INJECT_EVENTS是需要系统权限的,一些可能解决的方案在这里和这里有讨论到。
(译者注:请查看本人上一篇翻译的《Monkey源码分析番外篇之WindowManager注入事件如何跳出进程间安全限制》里面有更详细针对这个问题的描述)
Instrumentation m_Instrumentation = new Instrumentation(); m_Instrumentation.sendKeyDownUpSync( KeyEvent.KEYCODE_B );For touch events you can use:
//pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHT m_Instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,pozx, pozy, 0); m_Instrumentation.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,pozx, pozy, 0);
在应用内操作的话完全没有问题,但一旦跳出这个应用去触发按键事件的话就会崩溃。不是因为这个方法不工作,而是因为android开发人员做了限制。谢谢你们,android的开发者们,你牛逼!个屁。
By looking at sendPointerSync‘s code, you will quickly see it uses the same approach as presented in method 1). So this is the same thing, but packed nicely in a easy to use API:
通过分析sendPointerSync的对应代码,可以看到其实instrumentation使用到的注入事件方式其实和方法一提到的通过WindowManager.injectPointerEvents是一样的,所以穿的都是同一条内裤,只是Robotium出来走动的时候套上条时尚喇叭裤,而以上直接调用WindowManager的方式就犹如只穿一条内裤出街的区别而已。
public void sendPointerSync(MotionEvent event) { validateNotAppThread(); try { (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))) .injectPointerEvent(event, true); } catch (RemoteException e) { } }
linux以系统设备的方式向用户暴露了一套统一的事件注入接口/dev/input/eventX(其中X代表一个整数)。我们可以直接跳用而跳过以上的平台(android这个机遇linux的平台)限制问题。
For this to work, we will need root access, so this approach only works on a rooted device.
但是这需要工作的话,你需要rooted过的设备。
By default the eventX files have the permission set for 660 (read and write for Owner and Group only). To inject keys from our application, we need to make it writable. So do this first:
设备文件eventX默认是被设置为660这个权限的(Owner和同组成员有读写,而owner是root)。为了向这个设备注入事件,你必须让它能可写。所以请先做以下动作:
adb shell su chmod 666 /dev/input/event3You will need root to run the chmod command.
你将需要root权限来运行chmod命令。
Monkey源码分析番外篇之Android注入事件的三种方法比较
标签:monkey injectevent instrumentation
原文地址:http://blog.csdn.net/zhubaitian/article/details/40430053