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


    Android Software Engineer (f/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now

    Senior Android Software Engineer (f/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now

    Android Test Automation Engineer

    Komoot
    Remote
    • Full Time
    apply now

OUR VIDEO RECOMMENDATION

, ,

From Scoped Storage to Photo Picker: Everything to know about Storage

Persistence is a core element of every mobile app. Android provides different APIs to access or expose files with different tradeoffs.
Watch Video

From Scoped Storage to Photo Picker: Everything to know about Storage

Yacine Rezgui
Android developer advocate
Google

From Scoped Storage to Photo Picker: Everything to know about Storage

Yacine Rezgui
Android developer ad ...
Google

From Scoped Storage to Photo Picker: Everything to know about Storage

Yacine Rezgui
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
A few weeks ago I started with a simple question — how to work…
READ MORE
blog
One of the main functions of a mobile phone was to store contacts information.…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

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

Menu