您的位置:首页 > 移动开发 > Android开发

android系统消息之模拟

2013-10-15 10:24 295 查看
任何系统都有自己的系统消息机制,其中有一部分是开放给应用开发者的。比如windows系统提供sendkeys()方法来发送按键消息给当前活跃的窗口;比如android系统提供了handler的消息传输机制来进行线程间的消息传递。

在实际项目中,我碰到了一个需求,那就是通过pc远程控制装有android系统的设备,做一个类似于无线遥控的东东,需要支持触摸、拖拽、按键灯事件。这个需求可以分解为三块:pc端控制信息的输入,无线网络的控制命令传输,以及android端的系统事件模拟。

pc端控制信息的输入很好实现,可以直接在pc应用的点击等事件里判断
无线网络传输命令可以通过pc与android的socket通信实现,只需要传输命令字符串,再在通信两端进行字符串解析即可。具体的pc与android的socket通信方法可参考我的文章-pc与android的socket通信。
android的系统事件模拟在此需求中是相对较难的,也是本文重点要介绍的,下面就把我的心得归纳一下。

1、通过IwindowManager的injectKeyEvent接口来实现。

这种方法在android1.6以前是比较方便的,但在android1.6以后的版本,IwindowManager类被隐藏了,打了@hide标记,是为了安全考虑。不然恶意程序可以通过该接口随意控制设备就完蛋了。在之后的版本想通过这种方法实现,可以考虑跨进程调用,给程序打系统签名。具体可参考/article/2494829.html

2、通过Monkey实现。

据说最初是因为Monkey这个东西在设备里乱捣乱,乱发消息,很像一只调皮的猴子,才被命名为Monkey的。它实际上是为了实现自动化测试而用的,类似于工厂测试的工具。它可以生成系统事件,但是它无法生成指定的系统事件。可以通过shell命令调用Monkey并指定相关参数,包括生成事件的随机种子值(-s)、生成某种事件的百分比(–pct-touch 、–pct-motion)等等。Monkey会按照你设定的参数,自动的生成系统事件,从而测试各硬件以及驱动是否正常。用Monkey并不能实现我所需要的功能,但在我GOOGLE的过程中大量碰到这个东西,在此简要介绍一下,也作为技术储备记录下来。

3、通过Instrumentation实现。

Instrumentation类提供了send系列的方法,来实现系统消息的发送。其中sendKeyDownUpSync(int KeyCode),sendPointerSync(MotionEvent e)是比较重要的。

(1)sendKeyDownUpSync(int KeyCode)可以实现按键的点击,相当于模拟一个按键的一次down+up事件。比如要模拟BACK按钮的点击时,可用如下代码实现:

调用方式sendKey(KeyEvent.KEYCODE_BACK);

public static void sendKey(final int KeyCode) {

new Thread () {

public void run () {

try {

Instrumentation inst=new Instrumentation();

inst.sendKeyDownUpSync(KeyCode);

} catch(Exception e) {

Log.e(“Exception when sendKeyDownUpSync”, e.toString());

}

}

}.start();

}

(2)sendPointerSync(MotionEvent e)可以实现触摸的相关,其参数MotionEvent 主要有三类形式:

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,x,y,0);

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_MOVE,x,y,0);

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,x,y,0);

即对点(x,y)的按下、移动、以及抬起事件,通过这三种事件可以组合出任意的触屏点击、拖拽等事件。

例1:点击(x,y)

//就是一次down+up事件

Instrumentation inst=new Instrumentation();

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,x,y,0);

inst.sendPointerSync(e);

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,x,y,0);

inst.sendPointerSync(e);

例2:从(x1,y1)拖动到(x2,y2)

//一次down+若干次move+一次up事件

Instrumentation inst=new Instrumentation();

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,x1,y1,0);

inst.sendPointerSync(e);

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_MOVE,x?,y?,0);

inst.sendPointerSync(e);

。。。。。

MotionEvent e=MotionEvent.obtain(

SystemClock.uptimeMillis(),SystemClock.uptimeMillis(),MotionEvent.ACTION_UP,x2,y2,0);

inst.sendPointerSync(e);

我的需求最后用Instrumentation 实现了。

分享到此结束,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: