When we ask permission from the user on his phone, is there a way we can inform the OS not to ask this permission again? No matter what the user's response is.
If the program does not "desperately" require the permission, you can use SharedPreferences and store a variable called firstTime withe boolean value of true.
Then check in the onCreate method for that variable. if it is true, ask the permission then set the value to false and save it. Then when the user will rerun the application, it won't be the "FirstTime" so he won't be prompted with the permission.
SharedPreferences pref = this.getSharedPreferences("PACKAGE.NAME",MODE_PRIVATE);
Boolean firstTime = pref.getBoolean("firstTime",true);
if(firstTime){
//Ask for permissions here
pref.edit().putBoolean("firstTime",false).apply();
}
No, sorry. You would need to keep track of whether you asked the user for permissions, then use that information to determine whether or not to ask in the future.
When you ask the permission in any way like in the following, in the dialog that would be open to ask for permission there is a check box that by checking it, OS would not ask you for that permission any more:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
} else {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_WRITE_EXTERNAL_STORAGE);
}
}
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 currently writing some tests for an app. If the app does not have storage permission, a fragment pops up. I know how to grant permission with "grant permission rule" but is there a method to revoke permission?
No, that is not possible. Quote from https://developer.android.com/reference/android/support/test/rule/GrantPermissionRule:
Once a permission is granted it will apply for all tests running in the current Instrumentation. There is no way of revoking a permission after it was granted. Attempting to do so will crash the Instrumentation process.
What I can suggest is to wrap permission methods into some service and mock the value checking if the permission is granted
Yes, during testing its possible...Feuby gave a somewhat correct answer to the same question in this SO 2017 question
Android revoke permission at start of each test
Repeating his code
public static boolean checkCameraPermission(MainActivity thisActivity) {
return ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED;
}
public static void checkAndAskCameraPermission(final MainActivity thisActivity) {
if (!checkCameraPermission(thisActivity)) {
//No right is granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.CAMERA)) {
//Open a dialog explaining why you are asking permission then when when positive button is triggered, call this line
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.CAMERA},
CHECK_FOR_CAMERA_PERMISSION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.CAMERA},
CHECK_FOR_CAMERA_PERMISSION);
}
}
}
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.
I have an app to get user location with permissions.My target API=25 btw
Once I have given permission that It doesn't ask me for request permission anymore.
I have checked with debug my hasCoarseLocationPermission and hasFineLocationPermission always return 0(GRANTED) after giving permission.
But if I clear the app data asking for permission again(returns -1).But I always want to ask for permission when I open the application(must return -1 not 0).How can i do that?
Thanks in advance.
int hasCoarseLocationPermission=ContextCompat.checkSelfPermission(Kirala3.this, Manifest.permission.ACCESS_COARSE_LOCATION);
int hasFineLocationPermission = ContextCompat.checkSelfPermission(Kirala3.this, Manifest.permission.ACCESS_FINE_LOCATION);
I've tried also with PermissionChecker function but it returns same value(0).
Try with ActivityCompat
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Use this function for checking location permission
public boolean isLocationPermissionEnabled() {
return !(Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED);
}
Asking the user for permissions is not something an app is supposed to do at each launch. Once the app has been granted a permission, it has the permission until it is revoked by the user. What you describe is happening sounds correct:
First launch the app calls checkSelfPermission and gets back PERMISSION_DENIED
The app requests the permission and is granted by the user
Subsequent launches of the app also still call checkSelfPermission (which is exactly what it should do.) Now the returned value is PERMISSION_GRANTED. This is expected. No new permission request from the user is required.
Manually reset the app data and revoke the permissions in the Settings app
Launch the app again and checkSelfPermission returns PERMISSION_DENIED, the app must ask the user for permission again.
You may find this talk helpful: https://youtu.be/WGz-alwVh8A
You may also find this permissions helper library useful: https://github.com/hiqes/andele
I want to avoid ask others permission if the user not grant one.
For example: I ask for read/write external storage and camera, if the user deny the first, the library ask for camera permission, camera permission is redundant in this case.
RxPermissions.getInstance(getActivity()).request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) {
dispatchCamera();
} else {
showError();
}
});
I think I could use requestEach, but I dont know how stop to emit items if one permission is not granted and also I cant obtain the final result, if the user grant all permissions.
I suppose your problem was solved, but I gonna place answer, for somebody else, who get into same trouble.
All you need is takeUntil or takeWhile operator with requestEach(depends what stream behaviour you want). TakeUntil unsubscribe you from stream, and bring you only events with granted permissions and one of permission denied inclusive.If you want get only permission granted events without any of them == denied, pls use takeWhile opertator.
Just maybe you would have to experement with this code a while, cause I didnt use this library yet, and maybe something would behave not exactly as you want.
So code might be like this:
RxPermissions
.getInstance(getActivity())
.requestEach(Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.CAMERA)
.takeWhile(permission -> permission.granted)
//or use take untill if you want to get permission.granted == false event
//.takeUntil(permission -> !permission.granted)
.subscribe(granted -> {
if (granted) {
dispatchCamera();
} else {
showError();
}
});