【问题标题】:How to inject input events into own application on Android?如何在Android上将输入事件注入自己的应用程序?
【发布时间】:2021-02-07 00:06:37
【问题描述】:

我正在寻找一种方法,如何从特定应用程序中的代码将输入事件(如触摸或键盘事件)注入到自己的应用程序中。 进入 Android 操作系统或需要签名级权限 android.permission.INJECT_EVENTS 或 root 设备的其他应用程序 b/c,我必须避免两者。我寻找在没有任何提升权限的非 root 设备上运行的代码。

我在基于以下概念的代码方面取得了一些进展:

View v = findViewById(android.R.id.content).getRootView();
v.dispatchTouchEvent(e);

【问题讨论】:

  • 为什么需要这样做?如果是自己的应用,直接调用函数,而不是模拟触摸事件,不是更方便、更易于维护吗?除非你正在编写一个测试框架,在这种情况下,我会看看现有的是如何做到的。
  • @GabeSechan - 它是与任意应用程序链接的库的一部分,因此我没有这种可能性。测试框架是一个很好的近似,但它应该是生产级应用程序的一部分。

标签: android


【解决方案1】:

如果有任何问题,我认为 getRootView 和 dispatch 它应该可以正常工作。请简单介绍一下。

或者有一个更高级别但棘手的方法来做到这一点。 在 View.java 中,有一个名为 getViewRootImpl() 的隐藏 api,它将返回此 Activity 的 android.view.ViewRootImpl 对象。并且上面有一个叫做 enqueueInputEvent(InputEvent event) 的方法。这样就可以使用反射来获取这个方法了。

由于我刚刚完成了一个使用键盘向屏幕发送触摸命令的项目,我认为当您尝试将此类事件注入活动时,多点触摸可能是个问题。当您尝试将另一个手指发送到屏幕时。事件动作必须是 ACTION_POINTER_DOWN 并带有数组命名属性的索引移位。您还应该处理包含所有手指信息的属性和坐标数组,即使此时您只需要移动一根手指。设置为 properties[i].id 的手指 id 用于识别您的手指。但是数组的索引不是固定的。

        for (int i = 0; i < size; i++) {
            properties[i].id = fingerId;
            properties[i].toolType = MotionEvent.TOOL_TYPE_FINGER;

            coordses[i].x = currentX;
            coordses[i].y = currentY;
            coordses[i].pressure = 1;
            coordses[i].size = DEFAULT_SIZE;
        }
        event = MotionEvent.obtain(
                    mDownTime, SystemClock.uptimeMillis(),
                    ((size - 1) << MotionEvent.ACTION_POINTER_INDEX_SHIFT)
                            + MotionEvent.ACTION_POINTER_DOWN,
                    size,
                    properties, coordses, DEFAULT_META_STATE, DEFAULT_BUTTON_STATE,
                    DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
                    DEFAULT_EDGE_FLAGS, InputDevice.SOURCE_TOUCHSCREEN, DEFAULT_FLAGS);

【讨论】:

  • 我已经在尝试这种方法了。我观察到用户能够打开菜单但不能关闭的问题。
【解决方案2】:

我设法解决了这个问题,它不仅可以处理 Activity 根窗口,还可以处理为各种叠加层(例如菜单和对话框)创建的窗口。
代码在这里:https://github.com/TeskaLabs/Remote-Access-Android/blob/master/tlra/src/main/java/com/teskalabs/tlra/android/inapp/InAppInputManager.java

【讨论】:

    【解决方案3】:

    在我们自己的应用程序中,您只需使用输入 cli 命令:

      public static final void tapButton (int x, int y) throws IOException, InterruptedException {
             Runtime.getRuntime().exec("input tap " + x + " " + y);
        }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-07
      • 2018-07-05
      • 1970-01-01
      相关资源
      最近更新 更多