Monitoring and controlling app activities on an Android phone

Android’s AccessibilityService

When we need to detect which app is working in Android or we want to find out which apps are run most often, we need a tool to help us find out. Android has an awesome service called AccessibilityService for API 4, which helps us to do just that. The Android reference page provides this definition: “an accessibility service runs in the background and receives callbacks from the system when AccessibilityEvents are fired. Such events denote some sort of 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.”

What does this mean though? Here’s an example: in order to detect changes to the current top application, AccessibilityEvents needs to detect using EventType TYPE_WINDOW_STATE_CHANGED:

public void onAccessibilityEvent(final AccessibilityEvent event) {
 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
 //top application was changed
 }
}

Fixed event types

AccessibilityEvents has a lot of fixed event types: a couple of examples include TYPE_NOTIFICATION_STATE_CHANGED (Which represents the event of a Notification being shown) and TYPE_TOUCH_INTERACTION_START (which represents the event of the user starting to touch the screen). You can read more about different fixed event types here. Also AccessibilityEvents has a lot of information about any given event, like the package name of an application and so on.

Controlling other apps

Another interesting opportunity that Accessibility provides is that it allows you to control other apps from within your app. You can click butttons, or read and write information in other apps views. This function is only available from Jelly Bean onwards.

By way of example, here’s a code sample which detects and clicks a “Cancel” button in an uninstall app dialog:

public static final String UNINSTALLATION_PACKAGE_NAME = "com.android.packageinstaller";
@Override
public void onAccessibilityEvent(final AccessibilityEvent event) {
 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
 if (event.getPackageName() != null && UNINSTALLATION_PACKAGE_NAME.equals(event.getPackageName().toString())) {
 closeDialog(event);
 }
 }
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void closeDialog(AccessibilityEvent event) {
 AccessibilityNodeInfo nodeInfo = event.getSource();
 if (nodeInfo == null) {
 return;
 }
 List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("Cancel");
 for (AccessibilityNodeInfo node : list) {
 node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
 }
}

This article gives just a small taste of the masses of opportunities provided by this service. Have fun!