ActivityCompat.requestPermissions for targetSdkVersion 30 is not working - android

I have following permissions:
private static final String[] LOCATION_PERMISSIONS = {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
};
I try to request permissions in my code with following line (activity is my current activity ref):
ActivityCompat.requestPermissions(activity, LOCATION_PERMISSIONS, 1);
Everything works fine if I have targetSdkVersion 29 or lower in my build.gradle file. Permissions dialog appear, I can press button in it to grant permissions. Everythig is fine
But! After I changed target sdk to Android 11: targetSdkVersion 30 this functionality stop working.
Permission system dialog doesn't appear - and I can't grant location permissions for my app.
So can anybody help me? What am I wrong?
What should I change in my code - for correctly working with Android 11?
Now with targetSdkVersion 29 I can run my app under the android 11 emulator too. May be I shouldn't increment target sdk version to: 30 at all?
The solution is:
STEP 1: The app should request foreground location permissions :
private static final String[] FOREGROUND_LOCATION_PERMISSIONS = {
Manifest.permission.ACCESS_FINE_LOCATION, // GPS
Manifest.permission.ACCESS_COARSE_LOCATION, // GPS approximate location
};
STEP 2: The app should request background location permissions :
#RequiresApi(api = Build.VERSION_CODES.Q)
private static final String[] BACKGROUND_LOCATION_PERMISSIONS = {
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
};
Only in this order!
ActivityCompat.requestPermissions(activity, FOREGROUND_LOCATION_PERMISSIONS, 1);
// Check the first statement grant needed permissions, and then run the second line:
ActivityCompat.requestPermissions(activity, BACKGROUND_LOCATION_PERMISSIONS, 1);
If I firstly trying to request background permission - it will not work.
If I request only background permissions (without already granted foreground permissions) - it will not work.
I should request foreground permissions - and then after that I should request background permission - one by one.

On android 11 requests for background location permission will be implicitly denied if user haven't granted foreground location permission first.
Requests containing both foreground and background location permission at the same time are deemed invalid:
If your app targets Android 11 (API level 30) or higher, the system
enforces this best practice. If you request a foreground location
permission and the background location permission at the same time,
the system ignores the request and doesn't grant your app either
permission.
See Request location access at runtime

Related

Android Development: Able to Request a SinglePermission, but RequestMultiplePermissions shows no UI

Right now I am trying to ask the user for permission to track his/her fine location, following the docs. I was playing around with the code, and it seems that I'm able to request a single permission from the user no problem, but when trying to request multiple permissions (Fine, Course, Background location) the permission UI doesn't even show. What the heck gives? The code is nearly the same.
The code for multiple permissions is here
private fun requestPermissions() {
val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { granted ->
Timber.tag("ASDASD").e(granted.toString())
// We can check if either the FINE or APPROX permission location has been
// granted.
}
if (TrackingUtility.hasLocationPermissions(requireContext())) {
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
requestPermissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
} else {
requestPermissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
)
}
}
https://imgur.com/a/AIDCy4Q - Single permission request works
https://imgur.com/a/T8sTznX - Multiple permission doesn't show anything
I tried following the documentation to a T, but it seems that nothing wants to work unless I use a SingleRequestPermission
According to the documentation:
Even if several features in your app require location access, it's likely that only some of them require background location access. Therefore, it's recommended that your app performs incremental requests for location permissions, asking for foreground location access and then background location access. By performing incremental requests, you give users more control and transparency because they can better understand which features in your app need background location access.
And then then afterwards it highlights:
Caution: If your app targets Android 11 (API level 30) or higher, the system enforces this best practice. If you request a foreground location permission and the background location permission at the same time, the system ignores the request and doesn't grant your app either permission.
So for For Android 11 and up, if you request background location together with fine or coarse location the system will ignore the request. You need to request for background location separately (After being granted the fine or coarse location access)

Displaying images from SDCard in a Widget from MarshMallow

In a widget I display images from SDCard using remoteView.setImageViewUri(). This strategy works correctly except with MarshMallow:
The error is:
Unable to open content: file:///storage/emulated/0/Android/data/applicaitonPackage/files/file.png
open failed: EACCESS (Permission denied)
It's clear that this is a permission problem, but I don't know how to give permissions to the widget container and in theory (see Note 1) the images are already stored in shared storage.
Note 1: The directory where images are stored is shared storage under Environment.getExternalStorageDirectory()
Note 2: Application is not adapted to MarshMallow and uses targetSdkVersion=15
Note 3: Don't just reply explaining about new runtime permissions in MarshMallow. I already know permissions changes and that is not the problem because application is targeted SDKVersion 15 and the app hasn't any problem accessing the external storage, the problem is with the widget container that is the one that I suspect that doesn't has the permissions.
#Docs says
Requesting Permissions at Run Time
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality;
Therefore this make sense although you declare permission in manifest but still getting permission denied
I suggest you to read how to get runtime permission
http://developer.android.com/training/permissions/requesting.html
Here is the example provided by Docs
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Change permission as per you requirement
Hope it leads you to right direction
Did you have this permisstion in your Manifest file?
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
If I set the targetSdkVersion to 15 instead of 23 - will the android M users see the app and be able to download it (granting all permissions at runtime)?
Yes, the app will be available to M users and every permission is granted at install time.
`targetSdkVersion=15`
which is less than 23.User will able to download the app and use it it grants all the permission at run time. If you want to check the permission go to settings and grant the permission. If you want to use the android M permission module at run time you have to set the target SDK version to 23.
If set the targetSdkVersion=15 on android M and higher devices app getting crashed.
If you want to support android M users set targetSdkVersion=23and
handle permission runtime.

confused about android runtime permissions

So this whole new android runtime permissions has gotten me confused. My app is currently compiling and targetting version 23 which means I have to use runtime permissions. My app primarily uses the camera api which needs the camera permission so I added the runtime permissions before opening the camera as such:
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED)
{//ask permissions for camera
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
CameraPermissions);
}
else
{//permissions attained now you can open the camera
camera=Camera.open(getCid());
camera.setPreviewCallback(this);
initPreview(width, height);
startPreview();
startTimer();
}
I also check when I stop the camera:
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
camera.setPreviewCallback(null);
camera.release();
faceProc.release();
faceProc = null;
camera = null;
inPreview = false;
cameraConfigured = false;
}
The permission request is handled as such:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case CameraPermissions: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
StartUpCam();
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("How is this app going to work if you rejected the camera permission.... DUHHHH!!")
.setTitle("Rejected");
builder.setPositiveButton("Exit App", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//close application
closeApp();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
return;
}
}
}
So when the request is given it calls the StartUpCam which then tries to open the camera if the permissions is given. So here comes my questions, if I add this runtime permission checks how does this affect android devices lower than 6.0?? So a phone with version 5.0.1 will also get a prompt to give camera permissions? If I use runtime permissions, do I have to remove the camera permissions in the manifest file? Currently, I keep the camera permissions in the manifest along with the runtime permissions I don't know if that is correct or not. What if I lower the target and compiling sdk to 22 instead of 23, will android devices above 6.0 won't be able to download my app??? If I lower it to version 22 then I avoid all this headache...
I also check when I stop the camera
That is not needed, assuming that you do not try to stop a camera that you never opened. If the user revokes the permission while your app is running, your process is immediately terminated. As a result, you can never lose permissions in a running app. Since you checked for and had permission to open the camera, you already have permission to close it.
if I add this runtime permission checks how does this affect android devices lower than 6.0?
ContextCompat.checkSelfPermission() will return PackageManager.PERMISSION_GRANTED on older devices, assuming that you have the permission listed in the manifest.
So a phone with version 5.0.1 will also get a prompt to give camera permissions?
No.
If I use runtime permissions, do I have to remove the camera permissions in the manifest file?
No. Those elements are necessary on all Android versions.
What if I lower the target and compiling sdk to 22 instead of 23, will android devices above 6.0 won't be able to download my app?
Your compileSdkVersion has no impact on what versions of Android you support. Android 6.0 users will still be able to download your app.
If you lower your targetSdkVersion to 22 or lower, that too has no impact on what versions of Android that you support. Android 6.0 users will still be able to download your app. Doing this would mean that you could skip the runtime permission code. However, bear in mind that you still may not have permission. Users of Android 6.0 devices, running your targetSdkVersion 22 app, will grant the CAMERA permission by default. But, those users can still go into Settings > Apps, find your app, and revoke the permission. With the camera API, you basically cannot open the camera.
Tactically, going with targetSdkVersion of 22 or lower is certainly possible. Eventually, though, something is going to "force your hand" and require you to move to a targetSdkVersion of 23 or higher. So, someday, you will need to deal with the runtime permissions. Whether that is today or some day in the future is up to you do decide.
No if the Permission is in Menifest file. Android having less than 23 sdk won't receive a prompt about the permission, It will be the same like before.

Running "Targeting SDK 22" App In Android 6 (SDK 23)

I've noticed I get the following issue when someone tries to access my android application from Android 6 (SDK 23):
java.lang.SecurityException: "gps" location provider requires ACCESS_FINE_LOCATION permission.
Since it will take time to fix this issue, I decided to downgrade my application target SDK to SDK 22.
My questions are:
Is it possible to run "SDK 22 targeted" app in android 6 (SDK 23)?
What are the solutions for the SecurityException above?
*I already has the ACCESS_FINE_LOCATION permission granted in my Manifiest
Firstly, a device should be backward compatible (though this is not a blanket statement) Android 6.0 APIs to run the app with a lower SDK. You need to ensure you have the SDK 22 installed in your ide.
The other is there are extra issues regarding permissions for android 6.
See here:
Requesting Permissions at Run Time
And the example taken from there Check For Permissions:
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_CALENDAR);
And then Request the permissions you need:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
This answer contains a more comprehensive explanation.
https://stackoverflow.com/a/32084038/3956566

Grant permission required for EXTERNAL_STORAGE in Android M?

Will the Android permissions WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE trigger the new grant permission dialog of Android M?
I agree with Guillaume Perrot 's answer. I have met the similar question when I write the permission of READ_WRITE_EXTERNAL_STORAGE in AndroidManifest.xml
with no permissions showing up in the app by default , people need to switch the toggle button of storage in the app permissions.Then I modify my targetSdkVersion in build.gradle to less than 23(MNC) and other number related with sdkVersion, the app installed with the permissions on.
The other way is to write requestpermission function in the place that you need the permisson. The code is as follow:
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)==
PackageManager.PERMISSION_GRANTED) {
//do the things} else {
requestPermissions(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
AnyNumber);
Because I have less than 15 reputation so I can't vote for the Guillaume Perrot 's answer.Just use this way to show my idea.
I solved add this if check version for Android M
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
My answer is based on my tests on M Preview SDK version 2, using an emulator.
If you target MNC preview API level, WRITE_EXTERNAL_STORAGE is not granted by default and will be part of the new dynamic permission API.
You will see the storage permission as a toggle button in the new app permissions menu in device settings, and you can use Activity.requestPermissions to show the popup for that permission.
However if you target api level < MNC, it won't be classified as a dangerous permission, and thus will be granted without a way for the user to disable it (not showing up in permission settings), and you will not be able to compile code using Activity.requestPermissions anyway as the preview SDK enforces minSdkVersion="MNC" to use the new APIs.
This is a different behavior than location permissions: whatever the API level you target, the user will be able to turn location off in permission menu.
For the permission menu itself, the permission toggle state is ON by default if:
Target API level < MNC.
Target API level = MNC but you upgrade app on device from a previous install where target API level was less than MNC.
Otherwise you will see the toggle as OFF by default.
Hope it helps.
According to the docs:
Limited Permissions Granted at Install Time: When the user installs or updates the app, the system grants the app all permissions that the app requests that fall under PROTECTION_NORMAL.
So because READ_EXTERNAL_STORAGE is falling under PROTECTION_NORMAL , it won't trigger the dialog.
But because the level of WRITE_EXTERNAL_STORAGE is PROTECTION_DANGEROUS, it will fall under this behavior as described in docs:
User Grants Permissions at Run-Time: When the app requests a permission, the system shows a dialog to the user, then calls the app's callback function to notify it whether the permission was granted. If a user grants a permission, the app is given all permissions in that permission's functional area that were declared in the app manifest
Here is the sources for the protection level:
detailed list
According to Android docs you don't need to request permission about read and write external storage.
Edit: in the latest Android M release you need to ask for both read and write permissions
Storage permission falls under dangerous protection level, So all the dangerous protection level permissions will not be granted at install time in Android M, if App target SDK is set to 23. They will be given at run time.
And yes these permissions can be revoked at run time also.
No permission dialog will not be triggered automatically, you need to do a request by using API such as requestPermissions() method to show that native dialog.
Please check the dangerous level permission list here

Categories

Resources