zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    java.lang.NoClassDefFoundError: org/springframework/dao/support/DaoSupport
    project configuration is not up-to-date with pom.xml
    消息列队5
    消息列队4
    消息列队3
    聊聊常见的数据库架构设计方案?
    消息队列2
    消息队列1
    搜索引擎5
    搜索引擎4
  • 原文地址:https://www.cnblogs.com/techgogogo/p/4284822.html
Copyright © 2011-2022 走看看