Android UsageStatsManager

Android UsageStatsManager

Android UsageStatsManager

In this article we will talk about UsageStatsManager class and provide a sample application in gitHub.
https://github.com/ciitamjadibraheem/UsageStats.git

UsageStatsManager is a class added in android level 21 (Lollipop) which provides access to the device usage history and statistics.
With UsageStatsManager we can query UsageStats to retrieve statistics for installed application in Android devices.

In the following example we will retrieve statistics for used application in last 24 hours in simple steps:

 

1 – PACKAGE_USAGE_STATS permission:

The permission needed for the UsageStatsManager is a system-level permission and can be added to AndroidManifest file in the project :

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />

As a system-level permission it needs to be manually granted by the user, so first of all we need to check if the permission granted.

//import android.app.AppOpsManager;

private boolean getGrantStatus() {
        AppOpsManager appOps = (AppOpsManager) getApplicationContext()
                .getSystemService(Context.APP_OPS_SERVICE);
        int mode = appOps.checkOpNoThrow(OPSTR_GET_USAGE_STATS,
                android.os.Process.myUid(), getApplicationContext().getPackageName());
        if (mode == AppOpsManager.MODE_DEFAULT) {
            return (getApplicationContext().checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED);
        } else {
            return (mode == MODE_ALLOWED);
        }
    }

If not we will ask the user to grant the permission by clicking a button (enableBtn) that will redirect theuser to the usage access setting inside the device settings.
I prefer to do the check in onStart() part of the activity life cycle to check always if permission granted when the application jumps to foreground, in this case if user decided to remove the permission. The activity will notice the changes when it’s in foreground.
If the permission is granted another button is visible (showBtn) and by clicking this button it will start calculating the applications statistics.

//import android.widget.Button;
//import android.content.Intent;
//import android.provider.Settings;
//import android.view.View;

@Override
    protected void onStart() {
        super.onStart();
        if (getGrantStatus()) {
            showBtn.setOnClickListener(view -> {
                loadUsage();
            });
        } else {
            enableBtn.setOnClickListener(view -> {
                startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
            });
        }
    }

 

2 – Retrieve applications statistics:

Now after we granted the permission, we can use the UsageStatsManager to retrieve the statistics.
We can use „queryUsageStats“ which returns the application usage stats for the given time range, aggregated by the specified interval.

//import android.app.usage.UsageStats;
//import android.app.usage.UsageStatsManager;

UsageStatsManager usm = (UsageStatsManager) this.getSystemService(USAGE_STATS_SERVICE);
List<UsageStats> appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY,  System.currentTimeMillis() - 1000*3600*24,  System.currentTimeMillis());

Now we have a list of UsageStats objects (UsageStats contains usage statistics for an app package) but there is still the problem that the list has duplicated entries for each application depending on usage time, jumps to foreground and closing time.
This we can simply solve by grouping them by application in a SortedMap and set the map-key as total time in forground for each application.

//import java.util.SortedMap;

if (appList != null && appList.size() > 0) {
    SortedMap<Long, UsageStats> mySortedMap = new TreeMap<>();
    for (UsageStats usageStats : appList) {
        mySortedMap.put(usageStats.getTotalTimeInForeground(), usageStats);
    }
}

Now we have a list of usage stats containing all needed data about usage time for the installed applications for last 24 hours

We can use this list to build an ArrayAdapter, providing it to ListView and render a list of installed application usage stats.
You can check out our sample application from gitHub to get all applications icons, names and usage time from the UsageStats and render the result as a list-view in the view.
https://github.com/ciitamjadibraheem/UsageStats.git

Android UsageStatsManager

 

Amjad Ibraheem

15.09.2020