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. Actuallycontext.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
Horizontalscrollview: Auto-Scroll to End When New Views Are Added
How to Get Profile Like Gender from Google Signin in Android
Using Camera in the Android Emulator
Android Sms Receiver Not Working
How Does One Use Basic Authentication with Volley on Android
Users Does Not Define No Argument Constructor
How to Use the Android Volley API
Android Preferences: How to Load the Default Values When the User Hasn't Used the Preferences-Screen
How to Import Eclipse Project to Android Studio
Sharedpreferences and Thread Safety
How to Read CPU Frequency on Android Device
Android Emulator Camera Custom Image
Get File Path of Image on Android
Inflate a View/Layout into Another Layout