Android多屏设置中如何访问AccessibilityNode并点击副屏?

问题描述 投票:0回答:2

我正在构建一个支持两个显示器的 Android AccessibilityService。 想法是在第一个显示器上有一个可拖动的触摸区域(类似于触摸栏),用户可以通过拖动来移动辅助显示器上显示的光标。 请记住,我想在辅助显示器上运行独立应用程序,所以我不是在谈论用于多显示器设置的演示模式

我设法通过设置一个使用 android.permission.SYSTEM_ALERT_WINDOW 权限(Settings.canDrawOverlays())绘制应用程序的服务来完成这一部分。 它在第一个(触摸栏)显示屏上绘制触摸区域,并在辅助显示屏上绘制光标。当用户在触摸栏上拖动时,光标会移动 我可以获取辅助显示屏上光标的坐标,这样我就可以随时知道光标所在的位置。

现在的问题是实现点击交互。 我的计划是将该服务作为 AccessibilityService,以便当用户点击“触摸栏显示屏”时,允许我在“演示文稿显示屏”上执行点击,但我无法从辅助显示屏访问 AccessibilityNode,我只能访问通过“rootInActiveWindow”当前活动的显示。

这是当前代码(请记住,这是在 AccessibilityService 的范围内):

private fun click(action: Int = AccessibilityNodeInfo.ACTION_CLICK) {
    val nodeInfo = if(displayManager.displays.size > 1){
        windowsOnAllDisplays.get(displayManager.displays[1].displayId, emptyList()).firstOrNull()?.root ?: rootInActiveWindow
    } else {
        rootInActiveWindow
    } ?: return
    val nearestNodeToMouse = findSmallestNodeAtPoint(nodeInfo, cursorLayout.x, cursorLayout.y)
    if (nearestNodeToMouse != null) {
        logNodeHierachy(nearestNodeToMouse, 0)
        nearestNodeToMouse.performAction(action)
    }
    nodeInfo.recycle()
}

private fun findSmallestNodeAtPoint(sourceNode: AccessibilityNodeInfo, x: Int, y: Int): AccessibilityNodeInfo? {
    val bounds = Rect()
    sourceNode.getBoundsInScreen(bounds)
    if (!bounds.contains(x, y)) {
        return null
    }
    for (i in 0 until sourceNode.childCount) {
        val child = sourceNode.getChild(i)
        if(child != null) {
            val nearestSmaller = findSmallestNodeAtPoint(child, x, y)
            if (nearestSmaller != null) {
                return nearestSmaller
            }
        }
    }
    return sourceNode
}

因此,问题出在“rootInActiveWindow”和“windowsOnAllDisplays”提供程序上。 对我来说, windowsOnAllDisplays 始终返回空列表(因此我无法访问辅助显示器上的窗口),而“rootInActiveWindow”仅返回当前活动显示器的根(始终是“触摸栏”显示器) .

这是模拟器上具有两个显示屏的应用程序示例(底部是第一个(触摸栏)显示屏,顶部是带有光标的辅助显示屏)。

Multidisplay Android app with cursor and touchbar

您是否知道如何从辅助显示器访问 AccessibilityNode 以便能够执行单击,或者甚至对如何实现此目的有完全不同的想法?

android accessibility accessibilityservice system-alert-window android-multi-display
2个回答
1
投票

如果有人遇到同样的问题,我明白了:) 在所有显示器上获取窗口都有效,我只需要在辅助服务的 XML 配置中添加额外的标志。

除了“flagDefault”之外,还需要添加“flagRetrieveInteractiveWindows”以使其在所有显示器上返回非空窗口列表。

android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows"

之后,

windowsOnAllDisplays
将在辅助显示器上返回窗口(和AccessibilityNodes)。


0
投票

这是一个我非常感兴趣的用例(使用智能手机上的应用程序控制 VR 护目镜中的屏幕),您发布了应用程序吗?它是否有可能是开源的并且您可以分享以此为基础的工作基础? (我可能会

© www.soinside.com 2019 - 2024. All rights reserved.