If you choose ALLOW, it would just go and call like pre marshmallow; If you choose DENY, it means you have denied permission for user to access, then better we’d show an alert to guide user what’s going like following screenshot:

The idea here is, so user has denied permission, we need provide some explanation(i.e. rationale) to tell user why we need it. Also we provide two actions: Retry and I’m Sure. Click Retry, it would prompt permission asking alert again; Click I’m sure, then it just dismiss silently because user has explicitly known what he is doing.

So if you clicked Retry or you press call button second time, the permission requesting window will have an option: Never ask again.

The tricky part here what happens if user has denied with Never ask again checked?
It turns out in onRequestPermissionsResult, you could query shouldShowRequestPermissionRationale to tell whether user has denied with Never ask again option.

The code in onRequestPermissionsResult:

publicvoidonRequestPermissionsResult(intrequestCode,Stringpermissions[],int[]grantResults){if(requestCode==mRequestCode){Logger.t(mManifestPersmission);booleanhasSth=grantResults.length>0;if(hasSth){if(grantResults[0]==PackageManager.PERMISSION_GRANTED){//user accepted , make callLogger.d("Permission granted");if(this.mAffirmativeCallback!=null){this.mAffirmativeCallback.onPermissionConfirmed();}}elseif(grantResults[0]==PackageManager.PERMISSION_DENIED){booleanshould=ActivityCompat.shouldShowRequestPermissionRationale(mActivity,mManifestPersmission);if(should){//user denied without Never ask again, just show rationale explanationAlertDialog.Builderbuilder=newAlertDialog.Builder(mActivity,R.style.AppCompatAlertDialogStyle);builder.setTitle("Permission Denied");builder.setMessage("Without this permission the app is unable to make call.Are you sure you want to deny this permission?");builder.setPositiveButton("I'M SURE",newDialogInterface.OnClickListener(){@OverridepublicvoidonClick(DialogInterfacedialog,intwhich){dialog.dismiss();}});builder.setNegativeButton("RE-TRY",newDialogInterface.OnClickListener(){@OverridepublicvoidonClick(DialogInterfacedialog,intwhich){dialog.dismiss();requestPermission();}});builder.show();}else{//user has denied with `Never Ask Again`, go to settingspromptSettings();}}}}}privatevoidpromptSettings(){AlertDialog.Builderbuilder=newAlertDialog.Builder(mActivity,R.style.AppCompatAlertDialogStyle);builder.setTitle(mDeniedNeverAskTitle);builder.setMessage(mDeniedNeverAskMsg);builder.setPositiveButton("go to Settings",newDialogInterface.OnClickListener(){@OverridepublicvoidonClick(DialogInterfacedialog,intwhich){dialog.dismiss();goToSettings();}});builder.setNegativeButton("Cancel",null);builder.show();}privatevoidgoToSettings(){IntentmyAppSettings=newIntent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,Uri.parse("package:"+mActivity.getPackageName()));myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mActivity.startActivity(myAppSettings);}

So if shouldShowRequestPermissionRationale returns false, we will display an alert for go to app settings to allow user manually toggle permissions.

Last point, when request permission, we need a way to distinguish two case when shouldShowRequestPermissionRationale returns false. According to android documentation:shouldShowRequestPermissionRationale

To help find the situations where you need to provide extra explanation, the system provides the Activity.shouldShowRequestPermissionRationale(String) method. This method returns true if the app has requested this permission previously and the user denied the request. That indicates that you should probably explain to the user why you need the permission.
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. The method also returns false if the device policy prohibits the app from having that permission.

when shouldShowRequestPermissionRationale return false, it could be either user request permission first time or user has denied with Never ask again before. Hence we need modify request code a little bit:

privatestaticfinalintPERMISSIONS_REQUEST_CALL_PHONE=201;...booleanshould=ActivityCompat.shouldShowRequestPermissionRationale(mActivity,mManifestPersmission);if(permerssion!=PackageManager.PERMISSION_GRANTED){if(should){// should show some explanation alert, but here now, just prompt ask again requestPermission();}else{//TWO CASE://1. first time - system up - //request windowif(!PrefUtils.hasLocationPermissionBeenRequested(mActivity)){PrefUtils.markLocationPermissionBeenRequested(mActivity,true);requestPermission();}else{//2. second time - user denied with never ask - go to settings promptSettings();}}return;}

That’s all.

Pre marshmallow and code reuse

To make it work with pre marshmallow, we could encapsulate those logic in a helper.
So in helper, we could specify a general callback for affirmative actions. On pre marshmallow, you could just call that callback; on marshmallow, do permission flow:

publicclassPermissionHelper{publicinterfacePermissionAffirmativeCallback{publicvoidonPermissionConfirmed();}privatePermissionAffirmativeCallbackmAffirmativeCallback;publicstaticPermissionHelperpermissionHelper(PermissionTypetype,Activityactivity,PermissionAffirmativeCallbackcallback){returnnewPermissionHelper(type,activity,callback);}publicPermissionHelper(PermissionTypetype,Activityactivity,PermissionAffirmativeCallbackcallback){if(type==PermissionType.LOCATION){mManifestPersmission=Manifest.permission.ACCESS_FINE_LOCATION;mRequestCode=PERMISSIONS_REQUEST_LOCATION;mDeniedMsg="Without this permission the app is unable to find your location.Are you sure you want to deny this permission?";mDeniedNeverAskTitle="Unable to locate your position";mDeniedNeverAskMsg="You have denied the permission for location access. Please go to app settings and allow permission";}elseif(type==PermissionType.CALL){mManifestPersmission=Manifest.permission.CALL_PHONE;mRequestCode=PERMISSIONS_REQUEST_CALL_PHONE;mDeniedMsg="Without this permission the app is unable to make call.Are you sure you want to deny this permission?";mDeniedNeverAskTitle="Unable to make call";mDeniedNeverAskMsg="You have denied the permission for calling.. Please go to app settings and allow permission";}this.mActivity=activity;this.mAffirmativeCallback=callback;checkPermission();}privatevoidcheckPermission(){if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){intpermerssion=ActivityCompat.checkSelfPermission(mActivity,mManifestPersmission);booleanshould=ActivityCompat.shouldShowRequestPermissionRationale(mActivity,mManifestPersmission);if(permerssion!=PackageManager.PERMISSION_GRANTED){//...blablablareturn;}}if(this.mAffirmativeCallback!=null){this.mAffirmativeCallback.onPermissionConfirmed();}}//others}