4

I want to read the url user has entered in his browser. Here is my accessibility service code.

<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"
/>

In 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>

In 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());
}

Problem is i am getting views from content in the url in my rootview, not the top address bar. Any help is appreciated.

Xan
  • 74,770
  • 16
  • 179
  • 206
user2144735
  • 41
  • 1
  • 4
  • can you help on this https://stackoverflow.com/questions/63880266/how-to-get-url-from-browser-using-accessibility-service ? –  Sep 14 '20 at 08:17

3 Answers3

2

I use

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

And I listen to 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();
       }
    }
}

and it works!

cegprakash
  • 2,937
  • 33
  • 60
  • 2
    It is a good idea to recycle children that you access: `AccessibilityNodeInfo child = info.getChild(i); dfs(child); child.recycle();` – Ishamael Jan 03 '17 at 20:28
  • @cegprakash is there a way to change the url and redirect chrome to a different page? Can you help on this link: https://stackoverflow.com/questions/42731897/redirect-chrome-programmatically – kash May 23 '17 at 01:48
  • 2
    1) open chrome and url already loaded then it works. Now where is the scenario in which you will give another url in the address bar and hit enter, how can we handle that? – Ahmad Shahwaiz Feb 26 '18 at 12:18
  • do u receive any event when you hit enter? If so listen to that – cegprakash Feb 26 '18 at 15:36
  • In this line: AccessibilityNodeInfo child = info.getChild(i); "child" could be null, therefore it must be checked before calling recursively to dfs() in the next line. – TagFolks May 08 '18 at 18:49
  • I've never faced the null issue. Anyway I changed my code. – cegprakash Jul 23 '18 at 15:20
  • MAN you Saved my life, this is excellent answer, I don't know why it isn't marked as correct answer. – Mohamed Essam Aug 24 '20 at 20:16
  • can you help on this https://stackoverflow.com/questions/63880266/how-to-get-url-from-browser-using-accessibility-service ? –  Sep 14 '20 at 08:17
  • sorry man.. I'm not into android development these days. – cegprakash Sep 14 '20 at 09:09
0

Hmm. Your code more or less works for me (although I'm using different accessibility_service_config.xml settings, see below..), so long as Chrome is active and the address bar is actually displayed - one problem I've noticed is that Chrome automatically hides the address bar as soon as you start interacting with the page, and I haven't been able to find a way to get the url address from Chrome once it does that. For debugging / development purposes until you figure out a solution that works the best for you, you might want to change some of your accessibility_service_config.xml settings to be more general, making sure you start this project with getting all the accessibility events you possibly can ... Here's what I'm using:

<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" />

The differences being

  1. omitting the "android:packageNames" label (causes it to default to "all")

  2. using the most general possible settings for android:accessibilityEventTypes and android:accessibilityFeedbackType (not sure, but your using "typeWindowStateChanged" for android:accessibilityEventTypes might be part of your problem?)

  3. addition of android:canRequestFilterKeyEvents="true"

Good luck.

mtopinka
  • 127
  • 8
  • can you help on this https://stackoverflow.com/questions/63880266/how-to-get-url-from-browser-using-accessibility-service ? –  Sep 14 '20 at 08:17
-1

URL can be changed programmatically using the below code.

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);
                }
            }
        }

Using AccessibilityNodeInfo.ACTION_SET_TEXT I am also trying to perform click as you can see in the below code using AccessibilityNodeInfo.ACTION_CLICK but it does not work. Would like to know if it even possible to do that or not?? Thanks

XylemRaj
  • 772
  • 4
  • 13
  • 28