Such a new and awesome security functionality is RUN-TIME Permission
I am trying to understand it and make one demo for that But one question raise in my mind that when i am at handle user permission with DIALOG.
How to handle "Never ask Again"
Suppose my application MUST need Location/contact but user DENY it with "NEVER ASK AGAIN".
What can i do for that. Not all User understand my field is required.
ANY SUGGESTION?
First you need to implement OnRequestPermissionsResultCallback
Listener
of ActivityCompat
class in your Activity
and override void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
Method to check whether User is allowing or denying the permission
You can do like this. Here i check for permission access for WRITE_EXTERNAL_STORAGE
:
int REQUEST_STORAGE = 1;
private void checkPermissions() {
if (hasStoragePermissionGranted()) {
// you can do whatever you want
} else {
requestPermission();
}
}
public boolean hasPermissionGranted(){
return ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
public void requestPermission() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
ActivityCompat.requestPermissions(MainActivity.this, {Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_STORAGE);
}
}
Here is onRequestPermissionsResult()
method will be called when user allow or deny Permission from Runtime permission dialog.
You can also handle situation when User has checked never show Runtime Permission dialog for that you can show Snackbar or button to redirect user to your application settings page as you can not show permission dialog after user has checked "Never ask again"
.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_STORAGE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Storage permission is enabled
canSendAttachments = true;
systemLogsCheckbox.setEnabled(true);
} else if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivtity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//User has deny from permission dialog
Snackbar.make(mainLayout, getResources().getString("Please enable storage permission"),
Snackbar.LENGTH_INDEFINITE)
.setAction("OK", new View.OnClickListener() {
@Override
public void onClick(View view) {
ActivityCompat.requestPermissions(MainActivity.this, {Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_STORAGE);
}
})
.show();
} else {
// User has deny permission and checked never show permission dialog so you can redirect to Application settings page
Snackbar.make(mainLayout, getResources().getString("Please enable permission from settings"),
Snackbar.LENGTH_INDEFINITE)
.setAction("OK", new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", MainActivity.this.getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
})
.show();
}
}
}
Here i have used Snackbar
to show relevant message to user about Permission and mainLayout
is id of Activity's Main Layout
.
Hope it helps you.
I have created a library
that handle all the permissions
for you. you can find it in here:
PermissionHelper
To answer your question:
in order for you to know if the user checked
never show again you'll have to check against two things, if the permission is declined
and no explanation needed
if these two returned **true**
that means that the permission is no longer available to be asked again and the only solution to handle this case is to open the settings screen.
P.S: the library i created handle all these kind of scenarios for you and returns callbacks for you to decide what to do next!. the library has two implementations
- Manual implementation (which mean you'll have to implement the callback in your activity and listen to the returned callback from the library).
- Let the library request the permission for you and it'll as well return you a callback to let you decide what happens when the permission is permanently denied.
open your app setting when user chose "Nerver ask again"
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
my example to handle RuntimePermission:
https://github.com/henrychuangtw/RuntimePermission
Use Dexter library
or
Use PermissionsDispatcher:
Step 1 : use PermissionsDispatcher library by hotchemi (the library is annotation based, simple to use and well documented)
Step 2 : you have to provide 4 annotated methods and one of them is @OnNeverAskAgain(Manifest.permission.[permission_you_want]) as below
@OnNeverAskAgain(Manifest.permission.[permission_you_want])
void showNeverAsk() {
// handle here
}
Here is sample