Android UsageStatsManager – Tracking App Usage with Ease

In this article, we’ll explore the UsageStatsManager class in Android and guide you through building a simple app to track app usage. A sample project is available on GitHub: UsageStats Sample Application.

Introduced in Android API level 21 (Lollipop), UsageStatsManager provides access to app usage history and statistics on a device. With it, developers can query app usage statistics, such as the amount of time an app has been used within a specified time range. In this example, we’ll demonstrate how to retrieve usage statistics for apps over the last 24 hours.

Step 1 - Request the PACKAGE_USAGE_STATS Permission

To use UsageStatsManager, your app needs the PACKAGE_USAGE_STATS permission, which is a system-level permission. Add it to your AndroidManifest.xml:

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

Since this is a system-level permission, users must manually grant it in the device settings. To handle this, we need to check whether the permission is granted and, if not, guide the user to the settings to enable it. Here’s how to check if the permission is 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 permission is not granted, the user will be prompted to enable it by clicking a button (enableBtn). This redirects them to the usage access settings on the device. I recommend performing this check in the onStart() method of the activity lifecycle, which ensures that permission status is always verified when the app comes to the foreground. This way, if the user revokes the permission, the app will detect the change immediately. Once the permission is granted, a different button (showBtn) will appear. That allows the user to start retrieving the app usage statistics by clicking it.

				
					//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 -&gt; { loadUsage(); }); 
} else { 
enableBtn.setOnClickListener(view -&gt; { startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); }); 
} 
}

				
			
Step 2 - Retrieving App Usage Statistics

Once permission is granted, we can use UsageStatsManager to retrieve the app usage statistics. The queryUsageStats() method is used to get the app usage data for a specified time range, aggregated by the chosen interval (e.g., daily, hourly). Here’s an example of retrieving the usage data for the last 24 hours:

				
					//import android.app.usage.UsageStats; 
//import android.app.usage.UsageStatsManager; 
UsageStatsManager usm = (UsageStatsManager) this.getSystemService(USAGE_STATS_SERVICE); 
List appList = usm.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, System.currentTimeMillis() - 1000*3600*24, System.currentTimeMillis());

				
			

At this point, we have a list of UsageStats objects, which contain usage statistics for each app. However, the list may include duplicate entries for the same app, based on factors like usage duration, foreground activity, and closing time. To resolve this, we can group the entries by app in a SortedMap, using the total foreground time for each app as the key. This approach consolidates the data, eliminating duplicates.

				
					//import java.util.SortedMap; 
if (appList != null &amp;&amp; appList.size() &gt; 0) { 
SortedMap mySortedMap = new TreeMap(); 
for (UsageStats usageStats : appList) { mySortedMap.put(usageStats.getTotalTimeInForeground(), usageStats); 
} 
}

				
			

We now have a list of usage stats containing all the necessary data about the usage time of installed applications over the last 24 hours. This list can be used to create an `ArrayAdapter`, which can then be supplied to a `ListView` to display the app usage statistics. For a complete example of how to implement this, including how to fetch and display the app icons and names, check out the full source code on GitHub: UsageStats Sample Application.

@Transactional in Spring – how it works

This article provides an in-depth exploration of Spring Framework’s @Transactional annotation, detailing its functionality, implementation, advanced features, and best practices for effective transaction management in Java applications.

Weiterlesen »