方法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. 如何使用autolayout的UIView加入动画

    hi,all: 在经过了一番犹豫之后,我决定将我自己做的这个小APP的源代码发布给大家: 其出发点是和大家一起学习iOS开发,仅供学习參考之用. 之前代码是托管与gitlab 上的.今天我将其pull ...

  2. Java Swing创建自定义闪屏:在闪屏上添加Swing进度条控件(转)

    本文将讲解如何做一个类似MyEclipse启动画面的闪屏,为Java Swing应用程序增添魅力. 首先看一下效果图吧, 原理很简单,就是创建一个Dialog,Dialog有一个进度条和一个Label ...

  3. uva 10817 - Headmaster's Headache ( 状态压缩dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接: 点击打开链接 题目大意 某校有n个教师和m个求职者,已知每人的工资和能教的课程集合,要求支付最少的工资使得每 ...

  4. 两年前实习时的文档——MMC学习总结

    1概述 驱动程序实际上是硬件与应用程序之间的中间层.在Linux操作系统中,设备驱动程序对各种不同的设备提供了一致的訪问接口,把设备映射成一个特殊的设备文件,用户程序能够像其它文件一样对设备文件进行操 ...

  5. top使用命令

    top命令 第一行和uptime命令一样,都有系统的负载. 10:36:19 当前时间 up 1day .7min 系统执行时间.格式为天 时:分 1 user 当前登录用户数 load averag ...

  6. CentOS7 安装Bind

    简要记录安装Bind的过程以及遇到的问题 一. 虚拟机准备 准备了2台虚拟机,都是装的CentOS7 64_1的IP地址为192.168.1.160,2的地址为161.161作为DNS服务器. 二.下 ...

  7. MVC 如何在一个同步方法(非async)方法中等待async方法

    MVC 如何在一个同步方法(非async)方法中等待async方法 问题 首先,在ASP.NET MVC 环境下对async返回的Task执行Wait()会导致线程死锁.例: public Actio ...

  8. VARCHAR2 他们占几个字节? NLS_LENGTH_SEMANTICS,nls_language

    ORACLE初始化参数:NLS_LENGTH_SEMANTICS 初始化參数NLS_LENGTH_SEMANTICS用于指定CHAR列或VARCHAR2列的长度定义方式,默认值为BYTE. 当设置该參 ...

  9. Codeforces Round #306 (Div. 2) C

    意甲冠军 到不超过一个更100该整数字符串.采取随机从数间(不能拿). 问:是否有可能被剩下8除尽.假设能,出口YES和任选一个数字的其余病例的. 不能够,输出NO. 思路 想法题. 首先观察到.10 ...

  10. Map <STL>

    map的使用方法: #include <cstdio> #include <map> #include <string> using namespace std; ...