Wednesday 20 April 2016

Accessibility Services

An accessibility service runs in the background and receives callbacks by the system when Accessibility Events are fired. Such events denote some state transition in the user interface, for example, the focus has changed, a button has been clicked, etc. Such a service can optionally request the capability for querying the content of the active window. Development of an accessibility service requires extending this class and implementing its abstract methods.

Declaration:

 <service
            android:name=".MyAccessabilityService"
            android:label="@string/app_name_tracker"
            android:icon="@drawable/ic"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter android:priority="">
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibility_service_config" />
        </service>

accessibility_service_config.xml in res/xml folder:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:settingsActivity="androidapp.test.com.applicationtracker.MainActivity"
    android:accessibilityFlags="flagRetrieveInteractiveWindows"
    android:canRetrieveWindowContent="true"/>


Add Permission:

<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />


Retrieving window content:

import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;

public class Sample extends AccessibilityService {
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
       dumpWindow(event.getSource(), event.getEventType())
     
    }
    @Override
    public void onInterrupt() {

    }

 @Override
    public void onServiceConnected() {
        super.onServiceConnected();

        AccessibilityServiceInfo config = new AccessibilityServiceInfo();
        config.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
        config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
        config.flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE
        //config.flags = AccessibilityServiceInfo.DEFAULT;
        setServiceInfo(config);
    }
}

  public boolean dumpWindow(AccessibilityNodeInfo info,int eventID) {
   
     AccessibilityNodeInfo root = getRootNodeInfo(info);      
        if (root == null)
            return false;

        Queue<AccessibilityNodeInfo> mFringe = new LinkedList<>();
        mFringe.add(root);

        while (!mFringe.isEmpty()) {
            AccessibilityNodeInfo current = mFringe.poll();
            if (current.getText() != null && current.isVisibleToUser() ){            
                  Log.d("mFringe",""+current.getText().toString());
            }

            if (current.getText() != null ) {
                Log.d("saravanan===>", ""+current.getText());          
            }

            final int childCount = current.getChildCount();
            for (int i = 0; i < childCount; i++) {
                    AccessibilityNodeInfo child = current.getChild(i);
                if (child != null) {
                    mFringe.add(child);
                }
            }

        }

        return  return_flag;
    }

    public static  AccessibilityNodeInfo getRootNodeInfo(AccessibilityNodeInfo info) {
        AccessibilityNodeInfo root=null;
        if (info == null)
            return null;
             root = info.getParent();
            while (root != null) {
                AccessibilityNodeInfo parent = root.getParent();
                if (parent != null) {
                    root.recycle();
                    root = parent;
                } else {
                    break;
                }
        }
            return root == null ? info : root;

    }


No comments:

Post a Comment