I want to request permissions on runtime.I checked out official android developer website and it says that shouldShowRequestPermissionRationale returns true if permission was previously denied and returns false if permission has been denied AND never ask again checkbox was selected.
Then i saw this code in the site:
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation 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; 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.
}
My 2 questions are:
1)What happens if the user wasn't asked permission previously??We need to ask him right??Where do you put that code??
2)The above code asks for permission even when the user checked the never ask again checkbox(when shouldShowRequestPermissionRationale returns false,I.e,in the else block).How can u ask for permission when the user has checked that option??
To answer both your questions:
You can first use checkSelfPermission() to see if the permission has already been granted. If it has not been granted then you should check if shouldShowRequestPermissionRationale() returns true or false.
shouldShowRequestPermissionRationale() will return true in the following case:
When the user has denied the permission previously but has not
checked the "Never Ask Again" checkbox.
shouldShowRequestPermissionRationale() will return false in the following 2 cases:
When the user has denied the permission previously AND never ask
again checkbox was selected.
When the user is requesting permission for the first time.
So, what you can do is, if shouldShowRequestPermissionRationale() returns false
you can use a boolean preference value (default value as true) to check for
first time request of permission in the else case, if it is the first
request, then trigger requestPermissions
else if it is not the first request and the user has previously denied the request and also has checked the "Never ask again" checkbox, you can show a simple toast with the reason for unavailability of the feature that requires the permission and also mention the steps to manually enable it via settings.
Something like this:
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation 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 {
if(isFirstTimeRequest){
// No explanation needed; request the permission
// RESET PREFERENCE FLAG
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.
} else {
// User denied previously and has checked "Never ask again"
// show a toast with steps to manually enable it via settings
}
}
Related
From the doc, shouldShowRequestPermissionRationale indicates whether you should show permission rationale UI.
I found:
if change one permission to "Notify" and before first showing the permission-request-dialog, shouldShowRequestPermissionRationale return false
if deny the permission with the "Never ask again" checkbox selected, shouldShowRequestPermissionRationale return false
Then I met a problem, how to distinguish these two cases? I mean, in the following code snippet from Android developer:
if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...);
} else {
// You can directly ask for the permission.
requestPermissions(CONTEXT,
new String[] { Manifest.permission.REQUESTED_PERMISSION },
REQUEST_CODE);
}
In the case 2, though denied the permission with "Never ask again", the code still invokes requestPermissions?
I'm using the method startVoiceRecognition of class BluetoothHeadset. I can see from android vitals reports, a recurring security exception on Android Pie calling this method. I can't test it on emulator and I don't have a Pie phone to test. From documentation it seems only BLUETOOTH permission is needed and my apps has already that permission. Can someone help me to understand?
You need to request the permission RECORD_AUDIO, add it on your AndroidManifest:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
Read official documentation first. After Android 6.0 (API level 23) you should invoked Runtime Permission
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an explanation 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; 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.
}
} else {
// Permission has already been granted
}
Currently I am programming an android app which reads out the phone number of the user. Because the app is developed for SDK 23+ (target sdk 27) I have to request the read sms permission. If the user denies the permission the first time a dialog should appear where the use of the phone number is explained. Then the user can choose to request the permission once more or to type the phone number manually. If the user tiks "never ask again" a dialog should appear where the user is instructed to allow the permission via the settings.
To check if the user has ticked never ask again, I use the method shouldShowRequestPermissionRationale. But the method always returns false, even if I never ticked never ask again.
Here is the relevant code:
public class SettingsSettingsFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultCallback {
public void readNumber() {
if (person.getPhoneNumber() == null || person.getPhoneNumber().equalsIgnoreCase("")) {
if (checkSelfPermission(getActivity(), READ_SMS) != PackageManager.PERMISSION_GRANTED)
requestPermission();
else {
//read phoneNumber
}
}
//request permission send sms
private void requestPermission() {
requestPermissions(new String[]{Manifest.permission.READ_SMS}, PERMISSION_REQUEST_SEND_SMS);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_SEND_SMS)
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// user rejected the permission
boolean showRationale = shouldShowRequestPermissionRationale(Manifest.permission.SEND_SMS);
if (!showRationale) {
// user also CHECKED "never ask again" - show dialog
//show dialog: please allow in settings
} else if (counter < 2) {
// explain the permission, and give the user the possibility to ask once more
counter++;
}
}
Why is shouldShowRequestPermissionRationale always returning false?
The code is from here: Android M - check runtime permission - how to determine if the user checked "Never ask again"?
Thanks for help in advance.
According to android developers documentation of shouldShowRequestPermissionRationale():
method returns true if the app has requested this permission previously and the user denied the request.
If the user turned down the permission request in the past and chose the Don't ask again option in the permission request system dialog, this method returns false
If you haven't requested permission before it will return false because there is no need to pop the rational alert dialog.
This answer was very helpful for me to understand the issue.
Your requestPermission() is for READ_SMS, butshouldShowRequestPermissionRationale() is about SEND_SMS.
shouldShowRequestPermissionRationale() keeps returning false until user is asked for the "relevant" permission. Once requested, it returns true until user denies the same permission with "Never Ask Again" checked.
So, in your case, SEND_SMS is never requested. Therefore shouldShowRequestPermissionRationale(Manifest.permission.SEND_SMS) will keep returning false as expected. I made the same mistake before.
The shouldShowRequestPermissionRationale method returns false the first time.
I have the following code in a Fragment:
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
requestPermissions(new String[]{READ_CONTACTS}, 0);
} else {
Toast.makeText(getActivity(), "FALSE", Toast.LENGTH_SHORT).show();
snackBarInfo.dismiss();
}
Has anyone else encountered this?
Yes, this is by design. The idea is that if the permission is not granted and the shouldShowRequestPermissionRationale method returns false, then the app should request the permission from the OS.
When the user denies the permission request, then the shouldShowRequestPermissionRationale method will return true. At this point, you should show some custom UI to the user explaining why the permission is required.
See the Workflow for requesting permissions section in the Request app permissions page for further details.
I'm testing denial of permission to an application and I'm seeing that when asking for the state of the permission it returns granted instead of denied.
I'm checking state of permissions according to Google's Guide:
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.CAMERA)) {
// 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(getActivity(),
new String[]{Manifest.permission.CAMERA},
PERMISSIONS_REQUEST_TAKE_PHOTO);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Here is what it actually returns in the first if:
State "0" means PackageManager.PERMISSION_GRANTED
This is generating a java.lang.RuntimeException: Fail to connect to camera service error.
DEVICE IS A NEXUS 5X
Best regards.
Quotig #CommonsWare:
You're supposed to get PERMISSION_GRANTED for any targetSdkVersion below 23, even if the user toggled off that permission group in Settings. I suggest that you uninstall the app completely, set your targetSdkVersion to 23, and try it again.
This was the solution.
(This answer will be marked correct temporarily until commenter posts an answer)