How to Check If "Android.Permission.Package_Usage_Stats" Permission Is Given

How to check if android.permission.PACKAGE_USAGE_STATS permission is given?

By our investigation: if MODE is default (MODE_DEFAULT), extra permission checking is needed. Thanks to Weien's examination effort.

boolean granted = false;
AppOpsManager appOps = (AppOpsManager) context
.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
android.os.Process.myUid(), context.getPackageName());

if (mode == AppOpsManager.MODE_DEFAULT) {
granted = (context.checkCallingOrSelfPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) == PackageManager.PERMISSION_GRANTED);
} else {
granted = (mode == AppOpsManager.MODE_ALLOWED);
}

Request permission on PACKAGE_USAGE_STATS

Unfortunately you can't request the PACKAGE_USAGE_STATS at runtime like you do with a dangerous permission. The user need to manually grant the permission through the Settings application as explained in the UsageStatsManager documentation:

This API requires the permission
android.permission.PACKAGE_USAGE_STATS, which is a system-level
permission and will not be granted to third-party apps. However,
declaring the permission implies intention to use the API and the user
of the device can grant permission through the Settings application.

You can directly open the Apps with usage access activity with this code:

startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));

Here you can find an example of a basic app that shows how to use App usage statistics API.

UsageStatsManager is not working in android 11 with permission of PACKAGE_USAGE_STATS

After two days of struggle I have got the solution for my problem. Actually
context.getPackageManager().getInstalledApplications(PackageManager.GET_META_DATA); Should return the list of all the installed apps but in android 11 it'll only return the list of system apps. To get the list of all the applications(system+user) we need to provide an additional permission to the application i.e

Check if my application has usage access enabled

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;
}

AndroidTest with PACKAGE_USAGE_STATS permission

We have tried many approved. Finally, we succeeded.

The approved was use "adb shell input tap [x], [y]" to simulate tap, so it is like human tap the screen to trigger the switch.

This is the code us use.

private void grantPermission() throws InterruptedException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Context context = InstrumentationRegistry.getTargetContext();
final AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

// check if the app doesn't have permission
if (appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), context.getPackageName()) != AppOpsManager.MODE_ALLOWED) {
UiAutomation automation = InstrumentationRegistry.getInstrumentation().getUiAutomation();

//Open UsageAccessSettingsActivity
automation.executeShellCommand("am start com.android.settings/.Settings$UsageAccessSettingsActivity");
Thread.sleep(1000);

//Open the setting of the first app
automation.executeShellCommand(String.format("input tap %s %s", dpToPx(100), dpToPx(138)));
Thread.sleep(1000);

//Tap permit usage access
automation.executeShellCommand(String.format("input tap %s %s", dpToPx(100), dpToPx(164)));
Thread.sleep(1000);
}
}
}

public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

We have tried 6 AVDs on SDK 23 and 24 with hdip, xhdip and xxhdip. All works.

UPDATED[2/10]:

We found another easier way to do it. use "adb shell appops" commend.
This is ours code.

@Before
public void setUp() throws Exception {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Context context = InstrumentationRegistry.getTargetContext();
final AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

if (appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), context.getPackageName()) != AppOpsManager.MODE_ALLOWED) {
InstrumentationRegistry
.getInstrumentation()
.getUiAutomation()
.executeShellCommand("appops set " + context.getPackageName() + " android:get_usage_stats allow");
}
}
}

Error in Manifest.xml when adding PACKAGE_USAGE_STATS [Android Lollipop]

The AndroidManifest.xml error can be fixed by disabling lint errors. Specifically

Security - SignatureorSystemPermissions 

I guess after that the settings app will show your app.



Related Topics



Leave a reply



Submit