Pse*_*der 1 java android accessibility accessibilityservice
我需要使用其资源 ID(我知道)读取 3rd 方应用程序的资源。我参考了这个链接: 如何阅读窗口内容(使用accessibilityService)并使用draw over other app permission in Android? 为了实现这个功能。
问题:使用 event.getSource() 创建的 AccessibilityNodeInfo 对象源为 null。
鉴于我知道 Source 类,我想创建一个 AccessibilityNodeInfo 对象。
并非所有事件都与“源”节点相关联。事实上,大多数超级频繁发生的事件都没有。(触摸交互、窗口变化等)。您需要确保按具有源节点的事件进行过滤。话虽如此,我怀疑这是否是您想要的,具有源节点的事件很少会包含您正在寻找的节点。您可能希望在响应某些辅助功能事件子集后,探索从根节点开始的 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"
/>
Run Code Online (Sandbox Code Playgroud)
一些亮点:
Run Code Online (Sandbox Code Playgroud)android:accessibilityEventTypes="typeWindowsChanged|typeWindowContentChanged|typeViewScrolled"
此行旨在捕获在窗口上绘制了任何新内容的事件类型。注意:这些事件都没有自己的 event.getSource() 节点。每次都是空的!(恕我直言:这些事件的 event.getSource() 应该是根节点,但这只是我,问谷歌!!!)。
Run Code Online (Sandbox Code Playgroud)android:notificationTimeout="1000"
每秒仅获取一次特定类型的事件。非常适合节流频繁抛出的事件,如滚动事件。
Run Code Online (Sandbox Code Playgroud)android:canRetrieveWindowContent="true"
当我调用时不要抛出异常getRootInActiveWindow()。
Run Code Online (Sandbox Code Playgroud)android:accessibilityFlags="flagReportViewIds"
确保使用 AccessibilityNodeInfo 报告 viewID。
有了适当的无障碍服务配置,剩下的就很简单了。在可访问性事件的子集之后(上面的配置旨在捕获新的屏幕内容),在视图层次结构中搜索您的视图 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);
}
Run Code Online (Sandbox Code Playgroud)