Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if my application has usage access enabled

I'm using the new UsageStatsManager API to get current foreground application in Android 5.0 Lollipop. In order to use this API, the user must enable the application in the Settings->Security->Apps with usage access screen.

I send the user directly to this screen with this Intent:

 startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)); 

Now, I want to validate the user enabled my application. I wanted to do so like I validate the user enabled my application to use the NotificationListenerService but I have no idea what is the String key, if it even exists.

 Settings.Secure.getString(contentResolver, "enabled_notification_listeners"); // Tried Settings.ACTION_USAGE_ACCESS_SETTINGS as key but it returns null 

Second approach was to query the usage stats and check if it returns results (it returns an empty array when the app is not enabled) and it works most of the times but sometimes it returns 0 results even when my app is enabled.

 UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService("usagestats"); long time = System.currentTimeMillis(); List stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 10, time);  if (stats == null || stats.isEmpty()) {     // Usage access is not enabled } 

Is there a way to check if my application has usage access enabled?

like image 912
Lior Iluz Avatar asked Nov 30 '14 15:11

Lior Iluz


People also ask

How do I stop apps from using my access?

Things like Digital Wellbeing, Device Health Services, Google Play Services, and other stock apps should be left alone to ensure proper functionality, but most third-party apps can safely be disabled here. To do so, select the app from this list, then tap the toggle switch next to "Permit usage access."

How do I access an app using access?

Open Settings and tap Apps & notifications. Tap Permission manager to open the Android permission controller app. Click a specific permission from the app permissions list that you're interested in, like location. Here you'll see apps that have access to your location all the time or only while in use.


2 Answers

Received a great answer by someone on Twitter, tested working:

try {    PackageManager packageManager = context.getPackageManager();    ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);    AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);    int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);    return (mode == AppOpsManager.MODE_ALLOWED);  } catch (PackageManager.NameNotFoundException e) {    return false; } 
like image 99
Lior Iluz Avatar answered Sep 24 '22 12:09

Lior Iluz


I previously used the same code as Bao Le, but I've run into the problem that certain devices (e.g. VF-895N) report usage stats as enabled even when they're not. As a workaround I've modified my code like this:

public static boolean hasPermission(@NonNull final Context context) {     // Usage Stats is theoretically available on API v19+, but official/reliable support starts with API v21.     if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {         return false;     }      final AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);      if (appOpsManager == null) {         return false;     }      final int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());     if (mode != AppOpsManager.MODE_ALLOWED) {         return false;     }      // Verify that access is possible. Some devices "lie" and return MODE_ALLOWED even when it's not.     final long now = System.currentTimeMillis();     final UsageStatsManager mUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);     final List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, now - 1000 * 10, now);     return (stats != null && !stats.isEmpty()); } 

Successfully tested on multiple devices.

like image 22
Markus Avatar answered Sep 22 '22 12:09

Markus