Android:使用易访问性服务读取Google chrome URL

Android:使用易访问性服务读取Google chrome URL,android,google-chrome,accessibilityservice,Android,Google Chrome,Accessibilityservice,我想读取用户在其浏览器中输入的url。这是我的无障碍服务代码 <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityFlags="flagDefault" android:accessibilityEventTypes="typeWindowStateChanged" android:accessibilityFeedbackType="f

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

<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());
}
AccessibilityEvent(AccessibilityEvent事件)上的公共无效{ 调试(“在可访问性事件上”); getChromeUrl(getRootInActiveWindow()); } public void getChromeUrl(AccessibilityNodeInfo nodeInfo){ //使用节点信息树来标识适当的内容。 //现在我们将把它记录到logcat上。 Log.d(TAG,toStringHierarchy(nodeInfo,0)); } 私有字符串到字符串层次结构(AccessibilityNodeInfo,int-depth){ 如果(info==null)返回“”; 字符串结果=“|”; for(int i=0;i
问题是我从我的根视图的url中的内容获取视图,而不是顶部地址栏。感谢您的帮助

Hmm。您的代码或多或少对我有用(尽管我使用了不同的可访问性\u service\u config.xml设置,请参见下文…),只要Chrome处于活动状态并且地址栏确实显示出来-我注意到的一个问题是,一旦您开始与页面交互,Chrome就会自动隐藏地址栏,我还没能找到一种从Chrome上获取url地址的方法。出于调试/开发目的,在找到最适合您的解决方案之前,您可能希望将一些辅助功能\u service\u 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" />

区别在于

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

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

  • 添加android:canRequestFilterKeyEvents=“true”

  • 祝你好运。

    我用

    android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagRequestTouchExplorationMode|flagRequestEnhancedWebAccessibility|flagReportViewIds|flagRetrieveInteractiveWindows"
    
    我听Windows更改事件

    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();
           }
        }
    }
    
    AccessibilityEvent(AccessibilityEvent事件)上的公共无效{ if(AccessibilityEvent.eventTypeToString(event.getEventType()).contains(“窗口”)){ AccessibilityNodeInfo nodeInfo=event.getSource(); dfs(nodeInfo); } } 公共无效dfs(AccessibilityNodeInfo信息){ if(info==null) 返回; if(info.getText()!=null&&info.getText().length()>0) System.out.println(info.getText()+“类:”+info.getClassName());
    对于(inti=0;iURL),可以使用以下代码以编程方式更改

    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\u SET\u文本 我还尝试执行单击,正如您在下面的代码中看到的,使用 AccessibilityNodeInfo.ACTION_单击但不起作用。想知道是否有可能这样做??
    谢谢

    回收您访问的儿童是一个好主意:
    AccessibilityNodeInfo child=info.getChild(i);dfs(child);child.recycle();
    @cegprakash有没有办法更改url并将chrome重定向到其他页面?您能在这个链接上提供帮助:1)打开chrome和已经加载的url,然后它就可以工作了。现在,在地址栏中输入另一个url并按enter键的场景在哪里,我们如何处理呢?当您按enter键时,是否收到任何事件?如果收到,请在这一行中听:AccessibilityNodeInfo child=info.getChild(i);“child”可以为null,因此在下一行递归调用dfs()之前必须检查它。您能提供帮助吗?您能提供帮助吗?有没有办法打开新选项卡?