android系统消息之模拟

来源:互联网 发布:招聘软件 编辑:程序博客网 时间:2024/06/06 20:01

任何系统都有自己的系统消息机制,其中有一部分是开放给应用开发者的。比如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标记,是为了安全考虑。不然恶意程序可以通过该接口随意控制设备就完蛋了。在之后的版本想通过这种方法实现,可以考虑跨进程调用,给程序打系统签名。具体可参考http://blog.csdn.net/zzp16/article/details/7939852。

       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 实现了。

               分享到此结束,谢谢!

原创粉丝点击