There are basically 3 types of storage permissions in the android app settings:
My app requires the highest permission, so I use <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/> in manifest.xml.
Now I want to block the whole app, if the permission is not granted. So I tried using this code to check, if the highest permission is granted, but it always returns false.
if(ActivityCompat.checkSelfPermission(requireActivity(), Manifest.permission.MANAGE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
I also tried using WRITE_EXTERNAL_STORAGE, but it also returns true at the second option "Allow access to media only".
Conclusion
I am looking for a boolean function:
Returning true, if "Allow management of all files" is selected
Returning false, if "Allow access to media only" is selected
Returning false, if "Deny" is selected
Thank you.
Environment.isExternalStorageManager().
Related
How can I get instant transitions updates from geofence, when the app is running in the background?
Android background location limitations are preventing that from happening. Is there any way around it?
In Android 8: Apps in the background can only retrieve the user's location a few times per hour.
Before Android 10: Location permission is a single resource, and the application can be used everywhere with only one authorization (foreground and background).
In Android 10: The background location becomes an independent resource. In addition to the foreground request, the application must explicitly request this permission.
In Android 11: It is not possible to request background location permission at the same time as others, and the application must request it separately. In addition, requesting this permission will not prompt the user immediately like other permissions, but will take the user to the Settings page so that the user can update the permission level.
Before Android 10
Location permission only needs to be requested once, and apps in the foreground and background can be used. The user has only 2 options: authorize or not authorize.
#TargetApi(28)
fun Context.checkLocationPermissionAPI28(locationRequestCode : Int) {
if (!checkSinglePermission(Manifest.permission.ACCESS_FINE_LOCATION) ||
!checkSinglePermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
val permList = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
requestPermissions(permList, locationRequestCode)
}
}
private fun Context.checkSinglePermission(permission: String) : Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
Android 10
In this version, ACCESS_BACKGROUND_LOCATION is added, you can request this permission to obtain both the foreground and background permissions, like the following:
#TargetApi(29)
private fun Context.checkLocationPermissionAPI29(locationRequestCode : Int) {
if (checkSinglePermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
checkSinglePermission(Manifest.permission.ACCESS_COARSE_LOCATION) &&
checkSinglePermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) return
val permList = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION)
requestPermissions(permList, locationRequestCode)
}
private fun Context.checkSinglePermission(permission: String) : Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
Similarly, if the foreground permission (ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION) is requested, the Android operating system will automatically add the background permission (ACCESS_BACKGROUND_LOCATION) to the request. It is similar to the declaration of , whether ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION is declared, ACCESS_BACKGROUND_LOCATION will be added during the installation process.
The user now has three options: background (anytime), foreground (only during APP use), and reject.
Android 11
In addition to the above, developers also need to add some other steps.
There are two scenarios here. The first one is when only requesting permission from the front desk. In this case, we usually use ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION. However, the pop-up window for requesting authorization is slightly different from the previous one. In Android 11, Google added an option Only this time.
Please note that even if ACCESS_BACKGROUND_LOCATION is added to the list of permissions to request, the system will ignore it.
The second situation is that the application also needs background permission. For this, you must prepare your own dialog box and use a clear message to explain the use of the background location.
When the user agrees, he will be directed to the application settings page, where he can choose the permission level he wants to grant.
#TargetApi(30)
private fun Context.checkBackgroundLocationPermissionAPI30(backgroundLocationRequestCode: Int) {
if (checkSinglePermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) return
AlertDialog.Builder(this)
.setTitle(R.string.background_location_permission_title)
.setMessage(R.string.background_location_permission_message)
.setPositiveButton(R.string.yes) { _,_ ->
// this request will take user to Application's Setting page
requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), backgroundLocationRequestCode)
}
.setNegativeButton(R.string.no) { dialog,_ ->
dialog.dismiss()
}
.create()
.show()
}
In Android 11, we have 4 permission levels for location information.
When the user selects Allow all the time, the APP has the permission to use location information in the background.
I need the user to check and set permission to ACCESS_BACKGROUND_LOCATION ("Allow all the time") without the option to "Allow only while using the app". My GPS Tracking app needs to continue accessing location even when the application is minimised.
I have already permissions working for ACCESS_FINE_LOCATION for Android 9.
AndroidManifest.xml--------------------------------------------------->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
TrackingActivity.java (need to include ACCESS_BACKGROUND_LOCATION)---->
private void permissionCheck1() {
int permissionCheck1 = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionCheck1 != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} else {
grantedSetupGPSandMap();
}
}
I need the only permission option to be "Allow all the time" if possible. How do I set this up when checking and setting permissions?
For Android 10, if:
You omit ACCESS_BACKGROUND_LOCATION, and:
You use a foreground service with the android:foregroundServiceType="location" property set in the manifest, then:
The system will supply only the "Allow only while using the app" and "Deny" options to the user, in reference to the location permission.
I realize that's the exact opposite of what you asked for, but the point is, under this condition, "Allow only while using the app" effectively behaves like "Allow all the time", provided the aforementioned foreground service is running.
You will be able to receive location updates even when the app is offscreen. And the user does not have the option of only partially allowing location updates; they have to choose between fully allowing it, or fully denying it.
EDIT
This answer also assumes your targetSdkVersion is 29.
Background: I was trying out the new Tiles and TileService and decided to recreate the USB Tethering tile from CyanogenMod. I used reflection to access Connectivity manager's methods.
Problem: One Such method is the isTetheringSupported() which causes java.lang.SecurityException: You either need MANAGE_USERS or CREATE_USERS permission to: query user
So I added the permissions to the manifest but every time I use pm grant it returns "Permission is not a changeable permission type"
According to this I should not get this error when signed with the debug key.
Question: How do I get those permissions?
UPDATE:
Via Xposed it is possible to hook into the PackageManger and remove the below check and then do pm grant... to successfully grant whatever permission. If someone sees this and needs help to do so comment below I'll help you out.
OLD ANSWER
This code in the source
boolean isDevelopment =
((bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
doesn't check if your app is in development mode. It checks if the permission you are requesting has the protectionLevel attribute (set in manifest) set to development.
And the permission you are trying to get seems not to have any elements declared in the manifest that could pass this check:
if (!isNormal && !isDangerous && !isDevelopment) {
throw new SecurityException("Permission " + bp.name
+ " is not a changeable permission type");
}
Just stumbled upon this with another permission. Seems there's sadly no way to get it.
I had this exact same problem:
How permission can be checked at runtime without throwing SecurityException?
For the permission to READ_PHONE_STATE, because I was afraid it would pull an exception for devices which don't have phone compatibility. So, as the answer suggested, I created this method:
private boolean checkReadPhonePermission() {
String permission = "android.permission.READ_PHONE_STATE";
int res = checkCallingOrSelfPermission(permission);
return (res == PackageManager.PERMISSION_GRANTED);
}
Which should return true if the device has phone compatability and false if it doesn't. I then wrapped this bit of code which mutes the audio if the user is on the phone, with an if statement based on what the method returns:
For some reason, when I ran this on my emulator and put a toast to see what the method returns, I got false. The emulator device was a phone though, so I expected it to be able to allow that permission...Why is this happening?
Which should return true if the device has phone compatability and false if it doesn't
Um, no.
If you want to know whether the device has telephony capability, use hasSystemFeature(PackageManager.FEATURE_TELEPHONY) on PackageManager.
It was my understanding that Accountmanager.get(context).getAccounts could not return a securityexception because it does not require permissions. From the documentation:
Clients of this method that have not been granted the GET_ACCOUNTS
permission, will only see those accounts managed by
AbstractAccountAuthenticators whose signature matches the client.
https://developer.android.com/reference/android/accounts/AccountManager.html#getAccounts()
So it reads as though if you haven't got GET_ACCOUNTS then that's fine, but my app is crashing when calling the method with the following exception:
caller uid # lacks any of android.permission.GET_ACCOUNTS
Why would this happen?
Account[] accounts = AccountManager.get(parentActivity).getAccounts();
Your app lacks of the matching permission in your manifest.
Add
<uses-permission
android:name="android.permission.GET_ACCOUNTS" />
to your AndroidManifest.xml
Edit: For Android 6.0, request it at runtime: http://developer.android.com/training/permissions/requesting.html
GET ACCOUNTS:
Allows access to the list of accounts in the Accounts Service.
Protection level: dangerous