Android注入事件的三种方法比较

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

时间: 2024-11-09 06:51:42

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

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

原文:http://www.pocketmagic.net/2012/04/injecting-events-programatically-on-android/#.VEoIoIuUcaV 往下分析monkey事件注入源码之前先了解下在android系统下事件注入的方式,翻译一篇国外文章如下. Method 1: Using internal APIs 方法1:使用内部APIs This approach has its risks, like it is always with intern

Unity NGUI监听按钮点击事件的三种方法

NGUI版本:3.6.5 1.直接实现OnClick方法: 创建一个脚本,在脚本中实现OnClick()方法,绑定该脚本到按钮上,点击时就会实现OnClick函数内容: 2.使用SendMessage: 选择按钮后,打开Component——NGUI——Interaction,选择Button Message,为按钮添加一个UIButton Message组件: 然后设置UIButton Message中的参数即可: Target:接收按钮消息的游戏对象: Function Name:接收按钮消

[Android] Android 定时任务实现的三种方法(以SeekBar的进度自动实现为例)

一.采用Handler与线程的sleep(long)方法 二.采用Handler与timer及TimerTask结合的方法 三.采用Handler的postDelayed(Runnable, long)方法  布局文件: activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.c

android Button实现点击事件的三种方法

一.使用匿名内部类实现 onClickListener接口,通用: 二.让MainActivity实现onClickListener接口,这种方法适合于有多个组件时,这样用会更加的方便: 三.在XML文件中的相应组件中定义onClick方法,自定义的方法: 实现的源码: package com.example.clickbutton; import android.os.Bundle; import android.app.Activity; import android.view.Menu;

向其他进程注入代码的三种方法

http://huaidan.org/archives/838.html 原版地址: http://www.codeproject.com/threads/winspy.asp?df=100&forumid=16291&select=1025152&msg=1025152 pdf格式下载: http://netxfly.blogbus.com/files/1163491746.pdf 作者:Robert Kuster 翻译:袁晓辉([email protected]) 摘要:如何向

【转】Android——设置颜色的三种方法

以下三种方法均由[http://www.cnblogs.com/six-moon/p/4411383.html]转载. 1.利于系统自带的颜色类.如:TextView1.setTextColor(Android.graphics.Color.RED); 2.数字颜色表示法.如:TextView1.setTextColor(0x000000);//黑色 3.自定义颜色.如:TextView1.setTextColor(this.getResources().getColor(R.drawable.

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

1. public SharedPreferences getPreferences (int mode) 通过Activity对象获取,获取的是本Activity私有的Preference,保存在系统中的xml形式的文件的名称为这个Activity的名字,因此一个Activity只能有一个,属于这个Activity. 2. public SharedPreferences getSharedPreferences (String name, int mode) 因为Activity继承了Con

Android开发之去掉标题栏的三种方法,推荐第三种

Android:去掉标题栏的三种方法和全屏的三种方法 第一种:一般入门的时候经常使用的一种方法 onCreate函数中加入以下代码: requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏 注意这句一定要写在setContentView()方法的前面,不然会报错的 第二种:在AndroidManifest.xml文件中定义 <application android:icon="@drawable/icon" android:la

Android监听点击事件实现的三种方法

监听点击事件实现的三种方法:1.匿名内部类2.外部类3.直接实现接口 1.匿名内部类: package com.jereh.calculator; import android.content.Context; import android.os.Bundle; import android.os.PersistableBundle; import android.support.design.widget.FloatingActionButton; import android.support