【问题标题】:Accessing event input nodes in Android withour rooting无需root即可访问Android中的事件输入节点
【发布时间】:2016-01-31 06:31:58
【问题描述】:

我希望能够将不同的事件注入 Android 设备。经过一番搜索,我发现我可以通过访问Android OS中的事件输入节点来做到这一点,这些节点位于dev/input/eventX。一旦这些被访问,就可以进行读写操作,因此我可以注入事件。

问题是这些节点只能在有根设备中访问。如果我尝试在不生根的情况下使用它们,该过程将失败,如本文所述,

http://www.pocketmagic.net/programmatically-injecting-events-on-android-part-2/

我不想根设备以保留其保修。我在网上搜索了访问 Android 操作系统的可能方法,但我只找到了 root。

我认为可行的另一种方法是将应用程序编译为系统应用程序,但我不知道这是否会允许它访问(读取和写入权限)事件输入节点。这种方法会提供这些特权吗?

如果没有,是否有任何替代方法来生根,我可以在不生根设备的情况下为我的应用程序授予系统权限?

感谢任何帮助。

谢谢。

编辑:为了详细说明,我想注入不同的触摸事件。比如单点触控、滑动等。

【问题讨论】:

    标签: android code-injection android-permissions chroot


    【解决方案1】:

    您可以通过执行 Android 附带的 /system/bin/input 实用程序在设备上注入输入事件。您可以在this question 中看到一些使用它的示例(通过 adb)。输入实用程序似乎不需要任何特殊权限即可执行。

    要创建系统应用程序,您需要访问在为您的设备构建 Android 操作系统时使用的签名密钥 - 您不能只修改普通应用程序以赋予其系统权限。即使可以,它也不会授予您 root 访问权限(尽管您可能会使其成为 /dev/input/eventX 设备似乎也允许访问的输入用户组的一部分)。

    如果要注入触摸事件,可以使用Java Runtime class 的exec() 方法执行/system/bin/input 实用程序,或者只使用InputManager 中的injectMotionEvent() 方法。

    以下是从 Android 源代码中获取的方法,展示了如何注入 MotionEvent - 您可以查看完整的 source 以获取更多信息。

    /**
         * Builds a MotionEvent and injects it into the event stream.
         *
         * @param inputSource the InputDevice.SOURCE_* sending the input event
         * @param action the MotionEvent.ACTION_* for the event
         * @param when the value of SystemClock.uptimeMillis() at which the event happened
         * @param x x coordinate of event
         * @param y y coordinate of event
         * @param pressure pressure of event
         */
        private void injectMotionEvent(int inputSource, int action, long when, float x, float y, float pressure) {
            final float DEFAULT_SIZE = 1.0f;
            final int DEFAULT_META_STATE = 0;
            final float DEFAULT_PRECISION_X = 1.0f;
            final float DEFAULT_PRECISION_Y = 1.0f;
            final int DEFAULT_DEVICE_ID = 0;
            final int DEFAULT_EDGE_FLAGS = 0;
            MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, DEFAULT_SIZE,
                    DEFAULT_META_STATE, DEFAULT_PRECISION_X, DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID,
                    DEFAULT_EDGE_FLAGS);
            event.setSource(inputSource);
            Log.i(TAG, "injectMotionEvent: " + event);
            InputManager.getInstance().injectInputEvent(event,
                    InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
        }
    

    这些方法只允许您将事件注入您自己的应用程序窗口。

    如果您想将事件注入不属于您的应用的其他窗口,您需要在您的应用清单中声明额外的权限(READ_INPUT_STATE 和 INJECT_EVENTS)并使用 Android 操作系统签名密钥为您的应用签名.换句话说,将事件注入其他应用程序所需的权限永远不会授予普通应用程序(原因很明显)。

    【讨论】:

    • 非常感谢您提供这个有用的答案,请检查有关事件类型的问题,我已经更新了。我希望我将构建的应用程序能够注入触摸事件,那么这可以通过 /system/bin/input 实现吗?或者,我需要将它连接到计算机并从那里发送命令吗?另外,你能告诉我如何让我的应用程序成为输入用户组的一部分吗?谢谢。
    • 非常感谢您的回答,所以只是为了确保,如果我使用您在 mainfest 文件中提供的权限,使用 Android 签名密钥签署我的应用程序,然后我的应用程序将能够注入触摸整个系统中的任何窗口,对吗?假设我想在屏幕上的 x 和 y 坐标处打开另一个应用程序,然后拥有权限和签名密钥,我可以通过我的应用程序做到这一点而无需生根,对吗?请告诉我。非常感谢。
    • @Dania 我不知道你说的 在 x 和 y 坐标处打开另一个应用程序是什么意思 - 如果你想启动另一个应用程序,你应该使用 startActivity()有适当的意图。无论如何,根据source,INJECT_EVENTS 权限允许您将输入事件发送到任何窗口。我没用过,所以不能给你一个肯定的答案——和大多数编程特性一样,最简单的方法不是问人,而是自己尝试一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多