Blog Infos
Author
Published
Topics
,
Published
Using UsageStatsManager to check app usage history
🗒️ Contents
📌 Why not use ‘ActivityManager.getRunningTasks’?
📌 Alternative: Use ‘ActivityManager.getRunningAppProcesses’
📌 The Solution: Using `UsageStatsManager.queryEvents`
Step 1: 🔐 Requesting the Permissions
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.shubham0204.ml.ocmsclient">
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<application>
...
</application>
</manifest>

Snippet 1: Adding the PACKAGE_USAGE_STATS permission to AndroidManifest.xml

Job Offers

Job Offers


    Engineering Manager – Apps Lifecycle

    Zalando SE
    Berlin
    • Full Time
    apply now

    Kotlin Multiplatform Mobile Developer

    Touchlab
    Remote
    • Full Time
    apply now

    Android Build Engineer

    Pinterest
    San Francisco, CA | Seattle, WA
    • Full Time
    apply now
Load more listings

OUR VIDEO RECOMMENDATION

, ,

The Evolution of Android Graphics in Android 12/13

Android 12 and 13 both added significant new capabilities to Android platform graphics, including RenderEffect, RuntimeShader, and more. At the same time, RenderScript has been deprecated and we’ve introduced the RenderScript Intrinsics Replacement Toolkit. This…
Watch Video

The Evolution of Android Graphics in Android 12/13

Daniel Galpin
Android Developer Advocate and Fast Talking YouTuber
Google

The Evolution of Android Graphics in Android 12/13

Daniel Galpin
Android Developer Ad ...
Google

The Evolution of Android Graphics in Android 12/13

Daniel Galpin
Android Developer Advocat ...
Google

Jobs

Step 2: 🔑 Checking the status of the permission and requesting it
// The `PACKAGE_USAGE_STATS` permission is a not a runtime permission and hence cannot be
// requested directly using `ActivityCompat.requestPermissions`. All special permissions
// are handled by `AppOpsManager`.
private fun checkUsageStatsPermission() : Boolean {
val appOpsManager = getSystemService(AppCompatActivity.APP_OPS_SERVICE) as AppOpsManager
// `AppOpsManager.checkOpNoThrow` is deprecated from Android Q
val mode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
appOpsManager.unsafeCheckOpNoThrow(
"android:get_usage_stats",
Process.myUid(), packageName
)
}
else {
appOpsManager.checkOpNoThrow(
"android:get_usage_stats",
Process.myUid(), packageName
)
}
return mode == AppOpsManager.MODE_ALLOWED
}

Snippet 2: Checking the status of the PACKAGE_USAGE_STATS permission using AppOpsManager

 

In order to request the PACKAGE_USAGE_STATS permission, we can’t use the ActivityCompat.requestPermissions method or the ActivityResultContracts.RequestPermission() as this is not a runtime permission, as we discussed earlier. Instead, we need to navigate the user to the Settings page where the user enables this permission for the app,

if ( checkUsageStatsPermission() ) {
// Implement further app logic here ...
}
else {
// Navigate the user to the permission settings
Intent( Settings.ACTION_USAGE_ACCESS_SETTINGS ).apply {
startActivity( this )
}
}

Snippet 3: Requesting the PACKAGE_USAGE_STATS permission after checking the status the permission

 

Usage Data Settings as observed in a Android 9 device ( Samsung J7 ).

 

Step 3: 📱Retrieving Usage Events
var foregroundAppPackageName : String? = null
val currentTime = System.currentTimeMillis()
// The `queryEvents` method takes in the `beginTime` and `endTime` to retrieve the usage events.
// In our case, beginTime = currentTime - 10 minutes ( 1000 * 60 * 10 milliseconds )
// and endTime = currentTime
val usageEvents = usageStatsManager.queryEvents( currentTime - (1000*60*10) , currentTime )
val usageEvent = UsageEvents.Event()
while ( usageEvents.hasNextEvent() ) {
usageEvents.getNextEvent( usageEvent )
Log.e( "APP" , "${usageEvent.packageName} ${usageEvent.timeStamp}" )
}

Snippet 4: Requesting the usage events using the `usageStatsManager.queryEvents` method.

 

The output of code snippet 4. The last line in the output above shows the name of the calling package.

Step 4: Filtering user-installed apps ( Optional )
private fun getNonSystemAppsList() : Map<String,String> {
val appInfos = packageManager.getInstalledApplications( PackageManager.GET_META_DATA )
val appInfoMap = HashMap<String,String>()
for ( appInfo in appInfos ) {
if ( appInfo.flags != ApplicationInfo.FLAG_SYSTEM ) {
appInfoMap[ appInfo.packageName ]= packageManager.getApplicationLabel( appInfo ).toString()
}
}
return appInfoMap
}

Snippet 5: Getting a `Map` containing package names and labels of user-installed apps

 

Step 5: Check if user is unlocked ( from Android R )
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val userManager = getSystemService( Context.USER_SERVICE ) as UserManager
if ( userManager.isUserUnlocked ) {
// Access usage history ...
}
}

Snippet 6: Checking if the user is unlocked with UserManager

 

📍 We’re done!

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
This tutorial is the second part of the series. It’ll be focussed on developing…
READ MORE
blog
We recently faced a problem with our application getting updated and reaching slowly to…
READ MORE
blog
One of the main functions of a mobile phone was to store contacts information.…
READ MORE
blog
Splash screen is the initial screen you’ll see when you open your app. It…
READ MORE

Leave a Reply

Your email address will not be published.

Fill out this field
Fill out this field
Please enter a valid email address.

Menu