Search code examples
javaandroidaccessibilityserviceandroid-11

Is there a way to click a hyperlink in the a dialog using an AccessibilityService?


permission prompt image

I am trying to use Accessibility to click "Allow in settings" using my application's Accessibility Service. I have looked at the AccessibilityNode, and I do not see anything that's interactable in the TextView. Here is the output from the node:

Event Type: TYPE_WINDOW_CONTENT_CHANGED com.google.android.permissioncontroller android.widget.FrameLayout
 Source: 
0 | class name: android.widget.FrameLayout text: null content description: null input type 0 actions: ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_SHOW_ON_SCREEN  
1 | class name: android.widget.ScrollView text: null content description: null input type 0 actions: ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_SHOW_ON_SCREEN  
2 | class name: android.widget.TextView text: Change location access for AppName? content description: null input type 0 actions: ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ACTION_SET_SELECTION, ACTION_SHOW_ON_SCREEN  
2 | class name: android.widget.TextView text: This app wants to access your location all the time, even when you’re not using the app. Allow in settings. content description: null input type 0 actions: ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ACTION_SET_SELECTION, ACTION_SHOW_ON_SCREEN  
2 | class name: android.widget.Button text: Keep “While the app is in use” content description: null input type 0 actions: ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_CLICK, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ACTION_SET_SELECTION, ACTION_SHOW_ON_SCREEN 

There are only a handful of available actions for the TextView. I have attempted the available actions to the best of my knowledge with no success.

I have also explored the idea of a direct Intent to the "Allow in Settings" section but at the moment there are none. Our app requires location to be on at all times.


Solution

  • So what I ended up doing was writing a static function for getting spans from a CharSequence

    @NonNull
    ClickableSpan[] getClickableSpans(CharSequence text) {
        try {
          if (text instanceof Spanned) {
            Spanned spanned = (Spanned) text;
            return spanned.getSpans(0, text.length(), ClickableSpan.class);
          }
        } catch (Exception e) {
        //log exception
        }
        return new ClickableSpan[0];
    }
    

    and to use it

    public void onAccessibilityEvent(AccessibilityEvent) {
        AccessibilityNodeInfo nodeInfo = event.getSource();
        if (nodeInfo != null) {
            List<AccessibilityNodeInfo> nodeInfoList = nodeInfo.findAccessibilityNodeInfosByText(
              "This app wants to access your location all the time, even when you're not using the app. Allow in settings.");
            if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
                ClickableSpan[] spans = getClickableSpans(nodeInfoList.get(0).getText());
                if (spans.length > 0) {
                    spans[0].onClick(null);
                }
            }
        }
    }