方法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 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 );

  发送touch/mouse事件:

//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);

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

一旦你想要往其他窗口注入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 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的开发者们,你牛逼!个屁。

  通过分析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 shell
su
chmod 666 /dev/input/event3

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

作/译者

微信知识共享公众号

CSDN

天地会珠海分舵

TechGoGoGo

http://blog.csdn.net/zhubaitian

Android注入事件的三种方法比较的更多相关文章

  1. Monkey源代码分析番外篇之Android注入事件的三种方法比較

    原文:http://www.pocketmagic.net/2012/04/injecting-events-programatically-on-android/#.VEoIoIuUcaV 往下分析 ...

  2. spring注入bean的三种方法

    在Spring的世界中, 我们通常会利用bean config file 或者 annotation注解方式来配置bean. 在第一种利用bean config file(spring xml)方式中 ...

  3. Second Day: 关于Button监听事件的三种方法(匿名类、外部类、继承接口)

    第一种:通过匿名类实现对Button事件的监听 首先在XML文件中拖入一个Button按钮,并设好ID,其次在主文件.java中进行控件初始化(Private声明),随后通过SetOnClickLis ...

  4. 安卓开发笔记(十八):实现button按钮事件的三种方法

    Android开发中有三种主要的方式用于设置View的点击事件,1.创建内部类:2.主类中实现OnClickListener接口:3.使用匿名内部类.这三种方式都用到了OnClickListener接 ...

  5. 快速定位 Android APP 当前页面的三种方法(Activity / Fragment)

    方法一.通过adb命令打印当前页面: Android 如何快速定位当前页面是哪个Activity or Fragment (1)查看当前Activity :adb shell "dumpsy ...

  6. 拦截iOS系统导航栏返回按钮事件-三种方法

    方法一:在dealloc里面书写监听事件,因为只有pop才会调用dealloc,push不会掉用 - (void)dealloc {YLLog(@"123"); } 方法二:在- ...

  7. Qt 自定义事件(三种方法:继承QEvent,然后Send Post就都可以了,也可以覆盖customEvent函数,也可覆盖event()函数)

    Qt 自定义事件很简单,同其它类库的使用很相似,都是要继承一个类进行扩展.在 Qt 中,你需要继承的类是 QEvent. 继承QEvent类,你需要提供一个QEvent::Type类型的参数,作为自定 ...

  8. js&jquery:添加事件的三种方法和常用的一些事件

    一.添加事件的方法 1.EventTarget.addEventListener添加 获取事件目标元素,通过addEventListener函数添加 // Assuming myButton is a ...

  9. android 获取sharedpreference的三种方法的区别

    1. public SharedPreferences getPreferences (int mode) 通过Activity对象获取,获取的是本Activity私有的Preference,保存在系 ...

随机推荐

  1. Effective C++ -- 继承和面向对象设计

    32.确保你的public继承了模is-a关系 public继承意味着is-a关系(里氏替换原则),一切适用于基类也适用于派生类. 矩形继承正方形问题: 可实施与矩形的操作无法实施与正方形 在编程领域 ...

  2. Top与ROW_NUMBER

    论Top与ROW_NUMBER读取第一页的效率问题   前一段时间研究关于分页的问题,由于数据库属于百万级的,考虑了关于优化方面的问题.其中一个考虑是:第一页展现的频率肯定是最高的,所以我想第一页就使 ...

  3. IT该忍者神龟Jquery小工具easyUI物业摘要召回

    找了个时间看了下EasyUI插件.对它的插件感觉是非常舒服,特地把Easy UI的大部分功能属性做了一下汇总. 此属性列表请对比jQuery EasyUI 1.0.5,关于它的很多其它资讯请猛击这里. ...

  4. 网络的基本概念TCP, UDP, 单播(Unicast), 多播(多播)(Multicast)

    章相当低级,但相当重要! 我们周围一切差点儿都依赖于把事情抽象成低等级,并在某一点把它详细化,在一些设计概念中.接口层十分清晰而且目标非常集中,应用程序不用考虑操作系统怎样工作,操作系统也不用考虑硬件 ...

  5. BZOJ 1901 Zju 2112 Dynamic Rankings 与更改的树董事长

    标题效果:给定一个序列,单点变化,询价区间k大. 思维:假设没有变化.然后划分树就可以解决,但树的分工仍然是一棵树,它不支持的变化. 主席舒变化实际上是在外带fenwick右护套层值段树,但正确的值线 ...

  6. Putty设置自己主动两次登录

    有时你想登录到serverA,但serverA白名单,你刚刚从山寨机B登录了,所以每次你要登录到serverA.您必须先登录到山寨机B.然后登录到serverA. 我们能够用Putty的local p ...

  7. SharePoint 2013 禁用搜索服务

    原文:SharePoint 2013 禁用搜索服务 前言,在SharePoint2013中,对于硬件需求的提升,让我们虚机里安装总是一筹莫展,尤其开启了搜索服务以后,对于内存的消耗就更加严重,尤其对于 ...

  8. Python基本语法[二],python入门到精通[四] (转)

    写在前面 python你不去认识它,可能没什么,一旦你认识了它,你就会爱上它 回到顶部 v正文开始:Python基本语法 1.定义常量: 之所以上篇博客介绍了定义变量没有一起介绍定义常量,是因为Pyt ...

  9. c++界面设计皮肤工具

    1. 先进行软件界面设计,确定软件界面美术包装方案 2. 依据软件界面美术设计装方案制作对应的图片,图片格式请參见AUDK的帮助文档或皮肤工具SkinTool 的 Demo 3. 打开皮肤工具 Ski ...

  10. Swift——(三)Swift神奇的下划线

    在Swift在.有许多神奇的下划线,在这里,我们将看到神奇的汇总,我希望能够帮助其他很多学习Swift朋友. @Author: twlkyao转载或者引用请保留此行. 1.格式化数字字面量     通 ...