java - event.getSource 在辅助功能服务中返回 null。 (捕获第 3 方应用程序的源)

标签 java android accessibility accessibilityservice

我需要使用第 3 方应用程序的资源 ID(我知道)来读取该资源。 我引用的是这个链接: How to read window content (using accessibilityService) and evoking UI using draw over other app permission in Android?为了实现这个功能。

问题:使用 event.getSource() 创建的 AccessibilityNodeInfo 对象源为 null。

鉴于我知道 Source 类,我想创建 AccessibilityNodeInfo 的对象

最佳答案

并非所有事件都与“源”节点关联。事实上,大多数 super 频繁发生的事件并非如此。 (触摸交互、窗口更改等)。您需要确保按具有源节点的事件进行过滤。话虽如此,我怀疑这是否是您想要的,具有源节点的事件很少会包含您正在寻找的节点。在响应辅助功能事件的某些子集之后,您可能希望从根节点开始探索 AccessibilityNodeInfo 层次结构。

首先,确保您的服务配置正确。我认为看起来像这样的 service_config.xml 就足够了。

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:accessibilityEventTypes="typeWindowsChanged|typeWindowContentChanged|typeViewScrolled"
    android:accessibilityFlags="flagReportViewIds"
    android:canRetrieveWindowContent="true"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:notificationTimeout="1000"
    android:settingsActivity="com.moba11y.basicaccessibilityservice.SettingsActivity"
    />

其中的一些亮点:

android:accessibilityEventTypes="typeWindowsChanged|typeWindowContentChanged|typeViewScrolled"

此行旨在捕获在窗口上绘制任何新内容的事件类型。注意:这些事件都没有自己的 event.getSource() 节点。每次都会为空! (恕我直言:这些事件的 event.getSource() 应该是根节点,但这只是我的问题,请询问 Google!)。

android:notificationTimeout="1000"

每秒仅获取每种特定类型的事件一次。非常适合限制频繁引发的事件,例如滚动事件。

android:canRetrieveWindowContent="true"

当我调用 getRootInActiveWindow() 时不要抛出异常。

android:accessibilityFlags="flagReportViewIds"

确保使用 AccessibilityNodeInfo 报告 viewID。

有了正确的辅助服务配置,剩下的就非常简单了。在辅助功能事件的子集之后(上面的配置旨在捕获新的屏幕内容),在 View 层次结构中搜索您的 View ID。

public static void exploreNodeHierarchy(final AccessibilityNodeInfo nodeInfo, final int depth) {

    //Super important check! AccessibilityNodes can get invalidated at ANY time.
    if (nodeInfo == null) return;

    //Log the nodeINfo to string, with some tabs for visible parent/child relationships.
    Log.d(BasicAccessibilityService.class.getName(), new String(new char[depth]).replace("\0", "\t") + nodeInfo.toString());

    if (nodeInfo.getViewIdResourceName() == "the view id you have") {
        //Do work here.
    }

    for (int i = 0; i < nodeInfo.getChildCount(); ++i) {
        logNodeHierarchy(nodeInfo.getChild(i), depth + 1);
    }
}

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    exploreNodeHierarchy(getRootInActiveWindow(), 0);
}

关于java - event.getSource 在辅助功能服务中返回 null。 (捕获第 3 方应用程序的源),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45620584/

相关文章:

java - 密码要求程序

android - 重绘 Canvas ,用于更新然后在其上设置文本不起作用

javascript - 用于转到上一页的“alt+left”不适用于 testcafe,但手动工作正常

jquery - iframe 的可用性、可访问性、屏幕阅读器或任何其他开发、功能、跨浏览器问题是什么?

html - 如何在背景图像 Sprite 上获取 'alt' 文本标签

java - android - 减去edittext文本

java - 如何确保类中的某个字段在 java 的所有实例中具有不同且唯一的值?

java - 扫描仪 - 忽略文件末尾的新行

java - 服务中存储类的同步和/或互斥

java - 单击手机后退按钮时重置 Activity