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