方法1:使用内部APIs


  该方法和其他所有内部没有向外正式公布的APIs一样存在它自己的风险。原理是通过获得WindowManager的一个实例来访问injectKeyEvent/injectPointerEvent这两个事件注入方法。

IBinder wmbinder = ServiceManager.getService( "window" ); IWindowManager m_WndManager = IWindowManager.Stub.asInterface( wmbinder );

  ServiceManager和Windowsmanager被定义为存根Stubs类。我们根据我们的需要绑定上这些服务并访问里面的方法。 To send a key do the following: 通过以下方式发送一个事件:

// key downm_WndManager.injectKeyEvent( new KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A ),true );// key upm_WndManager.injectKeyEvent( new KeyEvent( KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A ),true );

  发送touch/mouse事件:

//pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHTm_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);

  这种方法能在你的应用中很好的工作,但,也仅仅只能在你的应用中而已

一旦你想要往其他窗口注入keys/touch事件,你将会得到一个强制关闭的消息:

E/AndroidRuntime(4908): java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission

  苦逼了吧,毕竟INJECT_EVENTS是需要系统权限的,一些可能解决的方案在这里这里有讨论到。 天地会珠海分舵注注:请查看本人上一篇翻译的《Monkey源码分析番外篇之WindowManager注入事件如何跳出进程间安全限制》里面有更详细针对这个问题的描述

方法2: 使用instrumentation对象


  相对以上的隐藏接口和方法,这个是比较干净(上面的是隐藏的,故需要用到android不干净不推荐的方法去获取)的方式,但不幸的事它依然有上面的JINECT_EVENTS这个只有系统应用(基本上就是android自己提供的,如monkey)才被允许的权限问题。

Instrumentation m_Instrumentation = new Instrumentation();m_Instrumentation.sendKeyDownUpSync( KeyEvent.KEYCODE_B );

  以下是触摸事件实例:

//pozx goes from 0 to SCREEN WIDTH , pozy goes from 0 to SCREEN HEIGHTm_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的开发者们,你牛逼!个屁。

  通过分析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) {}}

方法3:直接注入事件到设备/dev/input/eventX


  linux以系统设备的方式向用户暴露了一套统一的事件注入接口/dev/input/eventX(其中X代表一个整数)。我们可以直接跳用而跳过以上的平台(android这个机遇linux的平台)限制问题。但是这需要工作的话,你需要rooted过的设备。

  设备文件eventX默认是被设置为660这个权限的(Owner和同组成员有读写,而owner是root)。为了向这个设备注入事件,你必须让它能可写。所以请先做以下动作:

adb shellsuchmod 666 /dev/input/event3

  你将需要root权限来运行chmod命令。

作/译者

微信知识共享公众号

CSDN

天地会珠海分舵

TechGoGoGo

http://blog.csdn.net/zhubaitian

更多相关文章

  1. Android(安卓)JNI/NDK开发之基本姿势
  2. Android(安卓)实现ListView异步加载图片
  3. Android(安卓)Robotium小结
  4. [ZZ][Android]使用bindService启动服务
  5. Android(安卓)N调用系统安装APK方法报错原因整理及解决方案
  6. Android(安卓)多次点击事件的触发方法
  7. Android(安卓)Geofence的学习(二)继续翻译官方文档
  8. Android(安卓)结束进程的方法
  9. Android系统开发之七:添加Android(安卓)Native Service方法

随机推荐

  1. 微信转发度最高的十大Android文章
  2. android通过webservice验证用户
  3. android学习
  4. UML详解:解析Android消息处理机制:Handler/
  5. android 三种定位方式
  6. android 使用JavaMail发送邮件
  7. 【Android】第21章 2D图形和动画
  8. 【Android(安卓)okhttp源码解析 二】同步
  9. Android(安卓)下拉框第三方控件 NiceSpin
  10. Android模拟点击的四种方式