Accessing App Usage History In Android
source link: https://proandroiddev.com/accessing-app-usage-history-in-android-79c3af861ccf
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
đ Why not use âActivityManager.getRunningTasksâ?
As in most accepted answers on SO, you are most likely to use the ActivityManager.getRunningTasks
method to determine which application is in the foreground state. For those who are unaware of the foreground and background states of an Android app, hereâs a short description,
For our use-case, the foreground state would only mean that the app is not visible to the user ( maybe the home button is pressed; in such a case, the app moves to the Recents page ).
Getting back to the point, your very first observation in the officials docs of ActivityManager.getRunningTasks
will tell that the method is deprecated from Android Lollipop ( API level 21 ). And the reason Android suggests is quite convincing,
As of
Build.VERSION_CODES.LOLLIPOP
, this method is no longer available to third party applications: the introduction of document-centric recents means it can leak person information to the caller.
Youâll also bump into this observation by looking at the high-voted comments below the answers on SO, which suggested the use of ActivityManager.getRunningTasks
.
Accessing the recent activity of a users without consent, could force users to believe that your app is some sort of spyware installed on their device. Also, developers could study app-usage patterns robbed from your device to enhance their own apps, all from your private data. So, the decision of deprecating ActivityManager.getRunningTasks
from Android was a obvious step for the security of user-data.
đ Alternative: Use âActivityManager.getRunningAppProcessesâ
If youâre searching for a replacement of the deprecated ActivityManager.getRunningTasks
youâll probably find a solution using the ActivityManager.getRunningAppProcesses
method. But, due to some reason, the method returns only the package name of the current process i.e. the app which called this method. No other apps, which were used by the user, are returned through the method.
It seems that Android has restricted this method as well, in order to provide enhanced privacy to the user. Moreover, weâre looking for a way which is more official and safe from future deprecation by Android.
đ The Solution: Using `UsageStatsManager.queryEvents`
The UsageStatsManager
class provides access to the device usage history and statistics. Considering our use-case, weâre going to use the specific UsageStatsManager.queryUsageStats
method to check the userâs recent activity or the apps which were used recently, with the consent of the user.
Step 1: đ Requesting the Permissions
The official documentation for the UsageStatsManager
states,
Most methods on this API require the permission
android.permission.PACKAGE_USAGE_STATS
. However, declaring the permission implies intention to use the API and the user of the device still needs to grant permission through the Settings application.
So, its good to add this permission in our AndroidManifest.xml
,
Note, this is a special permission and not a runtime permission like CAMERA
or WRITE_EXTERNAL_STORAGE
which can be requested by the app. This is evident, as this is a sensitive permission, accessing userâs personal data, regarding which the user needs to be aware.
Step 2: đ Checking the status of the permission and requesting it
In the appâs logic, we first need to determine whether this is permission is granted by the user and if not, we need to request it. Unfortunately, we canât check the status of this permission using ContextCompat.checkSelfPermission
as it is a special permission. Special permissions are rather handled by the AppOpsManager
, which is the class used for managing all app-ops and access control.
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,
Step 3: đ±Retrieving Usage Events
Once the user has granted the permission, we can now access userâs device history and check which apps were used in the past with the userâs consent. We can now use the UsageStatsManager.queryEvents
method to retrieve the usage events.
- As observed in the code, the
queryEvents
method takes in two arguments,beginTime
andendTime
.beginTime
denotes the time ( in the past ) from which the events need to be retrieved, whereasendTime
denotes the time upto we need the events. Note, both these arguments are Unix Time values, which is evident as weâre usingSystem.currentTimeMillis()
in the code snippet above. - The
usageEvents.getNextEvent
will return the events in a chronological order, so you need to sort them.
If youâre targeting devices from Android R, make sure you have a look at Step 5.
Check the output below, each line shows the package name and the timestamp at which the package was accessed by the user.
Step 4: Filtering user-installed apps ( Optional )
As you may observe, the above output also contains some system applications like com.sec.android.app.launcher
which is the default launcher application on Samsung devices. This is because the user navigates to the home screen to open some other app or to change a device setting. You may wish to filter those system apps, such that only user-installed apps are visible in the output. We can create a method which returns a Map
containing user-installed apps with their package names and labels ( the name of the app, visible to the user ). We can filter the user-installed apps and also get their label ( in case you wish to process it further in your appâs logic )
Step 5: Check if user is unlocked ( from Android R )
If youâve checked the documentation for the UsageStatsManager.queryEvent
method, youâll discover,
Note: Starting from
Android R
, if the user's device is not in an unlocked state (as defined byUserManager#isUserUnlocked()
), thennull
will be returned.
So, from Android R we canât run this method when the device is locked. So, we need to check if the user is unlocked,
Snippet 6: Checking if the user is unlocked with UserManagerAlso, note that the UserManager.isUserUnlocked
method is available for API 24 and above, and hence weâll secured it in a if
statement.
This marks the end of our implementation. Connect to the a physical device and the app running!
đ Weâre done!
Hope you loved the blog! For any suggestions & queries, feel free to leave a comment. Keep reading, keep learning and have a nice day ahead!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK