【问题标题】:How to get view ID using Accessibility Service in android如何在 android 中使用 Accessibility Service 获取视图 ID
【发布时间】:2017-05-07 17:25:49
【问题描述】:

我是安卓的初学者。我想获取用户当前正在查看的视图的视图 ID。 我让我的问题更清楚一点。假设用户打开 MakeMyTrip 并导航到航班预订页面。现在我想获取该特定布局的 View id。 下面是我的服务类和xml配置文件。

public class MyAccessibilityService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    AccessibilityNodeInfo source = event.getSource();

    Log.d("ViewID",source.getViewIdResourceName());


}

@Override
public void onInterrupt() {

}



<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:packageNames="com.makemytrip" />

【问题讨论】:

  • 使用此代码,我的应用在启动 MakeMyTrip 应用时会崩溃。
  • 请添加您在LogCat 中看到的完整错误跟踪。

标签: android accessibilityservice


【解决方案1】:

我的猜测是你的电话

Log.d("ViewID",source.getViewIdResourceName());

正在这样做:

Log.d("ViewID", null)

window_content_changed 事件的源节点将是其内容更新的布局的根节点。这极不可能有 viewIDResourceName。大多数视图没有资源名称,通过直接访问视图可访问的视图 ID 只是自动生成的散列,没有任何意义。只有具有实际 viewResourceNames 的视图才会将其名称报告给无障碍服务。因此,如果元素没有R.id.viewResourceName,无障碍服务将报告null 的值。 Android Log 实用程序无法记录空值,您至少必须给它一个空字符串。

你应该这样做。

String viewIdName = source.getViewIdResourceName();
Log.d("ViewID", (viewIdName != null) ? viewIdName : "NO VIEW ID");

值得注意的是,对于您将其打印出来的位置,您总是会得到“NO VIEW ID”。您将不得不向下爬取视图层次结构以找到具有资源名称的视图。找到一些按钮或您已分配 ID 的东西!或者可能监听不同类型的可访问性事件。不过要小心!并非所有事件都有源节点!所以,如果你听

android:accessibilityEventTypes="typeAllMask"

您还需要检查空源节点。或者你会得到不同类型的空指针异常。

编辑:记录整个可访问性节点视图层次结构的基本递归函数。

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

    if (nodeInfo == null) return;

    String spacerString = "";

    for (int i = 0; i < depth; ++i) {
        spacerString += '-';
    }
    //Log the info you care about here... I choce classname and view resource name, because they are simple, but interesting.
    Log.d("TAG", spacerString + nodeInfo.getClassName() + " " + nodeInfo.getViewIdResourceName());

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

//Then call it like this from anywhere in your service, don't necessarily have to use the root node.  
logViewHierarchy(getRootInActiveWindow(), 0);

【讨论】:

  • 首先将视图 ID 存储在字符串中,然后将其传递给日志工作正常。但我想要的是该特定布局的视图 ID。我想知道用户何时打开该特定布局。
  • 使用我的代码,我得到了该布局中存在的每个视图的视图 ID,但不是布局 ID。
  • 该事件可能正在获取您正在寻找的布局的父级。向下爬取可访问性节点层次结构以找到它。
  • 请指导我如何爬取可访问性节点层次结构?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多