如何在没有 root 的情况下在 Android 上可靠地模拟触摸事件(如 Automate 和 Tasker)? [英] How can I reliably simulate touch events on Android without root (like Automate and Tasker)?

查看:127
本文介绍了如何在没有 root 的情况下在 Android 上可靠地模拟触摸事件(如 Automate 和 Tasker)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从作为后台服务运行的应用程序之外的 Java 可靠地模拟 Android 上的触摸事件(无需 root)?

虽然之前有人问过这个问题,大多数答案都使用 ADB.(例如如何在Android设备上模拟触摸事件?)

https://github.com/chetbox/android-mouse-cursor 提供使用辅助功能的一个很好的解决方案,但不是很可靠,因为并非所有视图都响应它,而且游戏在大多数情况下根本不响应.

private void click() {AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();if (nodeInfo == null) 返回;AccessibilityNodeInfonearestNodeToMouse = findSmallestNodeAtPoint(nodeInfo, cursorLayout.x, cursorLayout.y + 50);if (nearestNodeToMouse != null) {logNodeHierachy(nearestNodeToMouse, 0);NearestNodeToMouse.performAction(AccessibilityNodeInfo.ACTION_CLICK);}nodeInfo.recycle();}

<块引用>

这是https://github.com/chetbox/android-mouse 使用的当前代码-光标.

Android 版本为 8.0,库存 Android

有没有更好、更可靠的方法来从 Java 模拟这些触摸事件?提前致谢!

解决方案

正如所建议的,自 Nougat (API 24) 以来,模拟触摸事件的最佳方法是使用无障碍服务和 AccessibilityService#dispatchGesture 方法.

这是我模拟单击事件的方法.

//(x, y) 屏幕坐标私有静态 GestureDescription createClick(float x, float y) {//对于单次点击,1 毫秒的持续时间就足够了最终 int DURATION = 1;路径 clickPath = new Path();clickPath.moveTo(x, y);GestureDescription.StrokeDescription clickStroke =新的 GestureDescription.StrokeDescription(clickPath, 0, DURATION);GestureDescription.Builder clickBuilder = new GestureDescription.Builder();clickBuilder.addStroke(clickStroke);返回 clickBuilder.build();}//当手势完成或取消时调用回调回调 = 新的 AccessibilityService.GestureResultCallback() {@覆盖公共无效 onCompleted(GestureDescription 手势描述){super.onCompleted(gestureDescription);Log.d(TAG,手势完成");}@覆盖公共无效 onCancelled(GestureDescription 手势描述){super.onCancelled(gestureDescription);Log.d(标记,取消手势");}};//无障碍服务:包含对无障碍服务的引用//回调:如果您不关心手势终止,可以为 null布尔结果 = accessibilityService.dispatchGesture(createClick(x, y), callback, null);Log.d(TAG,手势已发送?"+结果);

要执行其他手势,您可能会发现 用于测试的代码 AccessibilityService#dispatchGesture 实现.

我将博客中的一篇文章与 Android 无障碍服务介绍一>.

How can I reliably simulate touch events on Android (without rooting) from Java outside my app which runs as a background service?

While this question has been asked before, most answers utilise ADB. (such as How to simulate touch events on Android device?)

https://github.com/chetbox/android-mouse-cursor offers a good solution using Accessibility, but is not very reliable as not all views respond to it, and games do not respond at all most of the time.

private void click() {
  AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
  if (nodeInfo == null) return;

  AccessibilityNodeInfo nearestNodeToMouse = findSmallestNodeAtPoint(nodeInfo, cursorLayout.x, cursorLayout.y + 50);

  if (nearestNodeToMouse != null) {
    logNodeHierachy(nearestNodeToMouse, 0);
    nearestNodeToMouse.performAction(AccessibilityNodeInfo.ACTION_CLICK);
  }

  nodeInfo.recycle();
}

This is the current code used by https://github.com/chetbox/android-mouse-cursor.

Android Version is 8.0, stock Android

Is there a better, more reliable way to simulate these touch events from Java? Thanks in advance!

解决方案

As suggested, the best way to simulate touch events since Nougat (API 24) is by using an accessibility service and the AccessibilityService#dispatchGesture method.

Here is how I did to simulate a single tap event.

// (x, y) in screen coordinates
private static GestureDescription createClick(float x, float y) {
    // for a single tap a duration of 1 ms is enough
    final int DURATION = 1;

    Path clickPath = new Path();
    clickPath.moveTo(x, y);
    GestureDescription.StrokeDescription clickStroke =
            new GestureDescription.StrokeDescription(clickPath, 0, DURATION);
    GestureDescription.Builder clickBuilder = new GestureDescription.Builder();
    clickBuilder.addStroke(clickStroke);
    return clickBuilder.build();
}

// callback invoked either when the gesture has been completed or cancelled
callback = new AccessibilityService.GestureResultCallback() {
    @Override
    public void onCompleted(GestureDescription gestureDescription) {
        super.onCompleted(gestureDescription);
        Log.d(TAG, "gesture completed");
    }

    @Override
    public void onCancelled(GestureDescription gestureDescription) {
        super.onCancelled(gestureDescription);
        Log.d(TAG, "gesture cancelled");
    }
};

// accessibilityService: contains a reference to an accessibility service
// callback: can be null if you don't care about gesture termination
boolean result = accessibilityService.dispatchGesture(createClick(x, y), callback, null);
Log.d(TAG, "Gesture dispatched? " + result);

To perform other gestures, you might find useful the code used for testing the AccessibilityService#dispatchGesture implementation.

EDIT: I link a post in my blog with an introduction to Android accessibility services.

这篇关于如何在没有 root 的情况下在 Android 上可靠地模拟触摸事件(如 Automate 和 Tasker)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆