【问题标题】:Android : Read Google chrome URL using accessibility serviceAndroid:使用无障碍服务读取 Google chrome URL
【发布时间】:2016-08-05 07:07:49
【问题描述】:

我想读取用户在浏览器中输入的网址。这是我的无障碍服务代码。

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFlags="flagDefault"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="0"
android:canRetrieveWindowContent="true"
android:packageNames="com.android.chrome"
android:description="@string/accessibility_description"
/>

在 AndroidManifest 中

<service android:name=".MyAccessibilityService"
        android:label="@string/accessibility_title"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService"/>
        </intent-filter>
        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/accessibility_service_config" />
    </service>

在 MyAccessibilityService 中

 public void onAccessibilityEvent(AccessibilityEvent event) {
    debug("On accessibility event");
    getChromeUrl(getRootInActiveWindow());
}

public void getChromeUrl(AccessibilityNodeInfo nodeInfo) {
    //Use the node info tree to identify the proper content.
    //For now we'll just log it to logcat.
    Log.d(TAG, toStringHierarchy(nodeInfo, 0));
}
private String toStringHierarchy(AccessibilityNodeInfo info, int depth) {
    if (info == null) return "";

    String result = "|";
    for (int i = 0; i < depth; i++) {
        if (result.contains("http")) {
            Log.d(TAG, "Found URL!!!!!!!!!!!!!!" + result);
        }
        result += "  ";
    }

    result += info.toString();

    for (int i = 0; i < info.getChildCount(); i++) {
        result += "\n" + toStringHierarchy(info.getChild(i), depth + 1);
    }

    return result;
}
private static void debug(Object object) {
    Log.d(TAG, object.toString());
}

问题是我从 rootview 的 url 中的内容获取视图,而不是顶部地址栏。任何帮助表示赞赏。

【问题讨论】:

标签: android google-chrome accessibilityservice


【解决方案1】:

我用

android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagRequestTouchExplorationMode|flagRequestEnhancedWebAccessibility|flagReportViewIds|flagRetrieveInteractiveWindows"

我会听 Windows Changed Event

public void onAccessibilityEvent(AccessibilityEvent event) {
    if(AccessibilityEvent.eventTypeToString(event.getEventType()).contains("WINDOW")){
         AccessibilityNodeInfo nodeInfo = event.getSource();
         dfs(nodeInfo);
    }
}

public void dfs(AccessibilityNodeInfo info){
    if(info == null)
        return;
    if(info.getText() != null && info.getText().length() > 0)
        System.out.println(info.getText() + " class: "+info.getClassName());
    for(int i=0;i<info.getChildCount();i++){
       AccessibilityNodeInfo child = info.getChild(i);
       dfs(child);
       if(child != null){
          child.recycle();
       }
    }
}

它有效!

【讨论】:

  • 回收您访问的孩子是个好主意:AccessibilityNodeInfo child = info.getChild(i); dfs(child); child.recycle();
  • @cegprakash 有没有办法更改 url 并将 chrome 重定向到不同的页面?你能在这个链接上帮忙吗:stackoverflow.com/questions/42731897/…
  • 1) 打开 chrome 和 url 已经加载然后它工作。现在在哪里你会在地址栏中输入另一个 url 然后回车,我们该如何处理呢?
  • 当你回车时你收到任何事件吗?如果是这样,请听
  • 在这一行:AccessibilityNodeInfo child = info.getChild(i); "child" 可以为 null,因此必须在下一行递归调用 dfs() 之前对其进行检查。
【解决方案2】:

嗯。你的代码或多或少对我有用(尽管我使用不同的accessibility_service_config.xml设置,见下文..),只要Chrome处于活动状态并且地址栏实际显示 - 我注意到的一个问题是Chrome自动一旦您开始与页面交互,就会隐藏地址栏,一旦这样做,我就无法找到从 Chrome 获取 url 地址的方法。在您找到最适合您的解决方案之前,出于调试/开发目的,您可能希望将一些可访问性_service_config.xml 设置更改为更通用,确保您在启动该项目时获取所有可能的可访问性事件...这是我正在使用的:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFlags="flagDefault"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:notificationTimeout="0"
    android:canRetrieveWindowContent="true"
    android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity"
    android:canRequestFilterKeyEvents="true" />

区别在于

  1. 省略“android:packageNames”标签(使其默认为“all”)

  2. 对 android:accessibilityEventTypes 和 android:accessibilityFeedbackType 使用最通用的可能设置(不确定,但您对 android:accessibilityEventTypes 使用“typeWindowStateChanged”可能是您的问题的一部分?)

  3. 添加 android:canRequestFilterKeyEvents="true"

祝你好运。

【讨论】:

【解决方案3】:

可以使用以下代码以编程方式更改 URL。

AccessibilityNodeInfo source = accessibilityEvent.getSource();
            if (source != null & 
"android.widget.EditText".equals(accessibilityEvent.getClassName())) {
                Bundle arguments = new Bundle();

                String typedDetails = source.getText().toString();

                Log.d("typed text", source.getText().toString());

                if (typedDetails.contains("facebook")) {
                    //showOverlay();
//                    }
                    arguments.putCharSequence(AccessibilityNodeInfo
                            .ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, 
"file:///android_asset/redirect.html");
                    final AccessibilityNodeInfo clickableParent = 
source.getParent();

                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

source.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);

source.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                }
            }
        }

使用 AccessibilityNodeInfo.ACTION_SET_TEXT 我也在尝试执行点击,您可以在下面的代码中使用 AccessibilityNodeInfo.ACTION_CLICK 但它不起作用。想知道是否有可能做到这一点? 谢谢

【讨论】:

  • 有什么方法可以打开新标签页吗?
猜你喜欢
  • 2021-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多