Android的M – 检查运行时权限 – 如何确定用户选中“永不再问”?

根据这个: http : //developer.android.com/preview/features/runtime-permissions.html#coding一个应用程序可以检查运行时权限和请求权限,如果它尚未被授予。 随后将显示以下对话框:

在这里输入图像描述

如果用户拒绝重要权限,应用程序应该显示为什么需要权限以及影响下降的解释。 该对话框有两个选项:1)再次重试(再次请求权限),2)拒绝(应用程序将没有该权限)。

如果用户选中“永不再问”,则不应该显示第二个带解释的对话框,特别是如果用户之前已经拒绝了一次。 现在的问题是:我的应用程序如何知道用户是否已经检查了“再也不问”? IMO的onRequestPermissionsResult(int requestCode,String []权限,int [] grantResults)不会给我那个信息。

第二个问题是:Google是否有计划将自定义消息合并到权限对话框中,以解释为什么应用程序需要权限? 那样的话,永远不会有第二个对话,这肯定会带来更好的效果。

开发人员预览版2对应用程序请求的权限进行了一些更改(另请参阅http://developer.android.com/preview/support.html#preview2-notes )。

第一个对话框现在看起来像这样:

在这里输入图像描述

没有“从不再显示”checkbox(与开发人员预览1不同)。 如果用户拒绝该权限,并且该权限对应用程序是必不可less的,则可以提供另一个对话框来解释该应用程序请求该权限的原因,例如:

在这里输入图像描述

如果用户再次拒绝,应用程序应该closures,如果它绝对需要该权限或保持有限的function运行。 如果用户重新考虑(并select重试),则再次请求许可。 这次提示符是这样的:

在这里输入图像描述

第二次显示“永不再问”checkbox。 如果用户再次拒绝,并勾选checkbox,则不会再发生任何事情。 是否勾选checkbox可以通过使用Activity.shouldShowRequestPermissionRationale(String)来确定,例如:

if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) {... 

这就是Android文档所说的( https://developer.android.com/training/permissions/requesting.html ):

为了帮助您find需要提供额外说明的情况,系统提供了Activity.shouldShowRequestPermissionRationale(String)方法。 如果应用程序以前请求过此权限,并且用户拒绝了此请求,则此方法返回true。 这表明你应该向用户解释为什么你需要许可。

如果用户过去拒绝了权限请求,并且在权限请求系统对话框中select了“不要再询问”选项,则此方法返回false。 如果设备策略禁止应用程序拥有该权限,该方法也会返回false。

要知道用户是否拒绝“永不再问”,您可以在用户未授予权限时再次检查onRequestPermissionsResult中的shouldShowRequestPermissionRationale方法。

 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_PERMISSION) { // for each permission check if the user granted/denied them // you may want to group the rationale in a single dialog, // this is just an example for (int i = 0, len = permissions.length; i < len; i++) { String permission = permissions[i]; if (grantResults[i] == PackageManager.PERMISSION_DENIED) { // user rejected the permission boolean showRationale = shouldShowRequestPermissionRationale( permission ); if (! showRationale) { // user also CHECKED "never ask again" // you can either enable some fall back, // disable features of your app // or open another dialog explaining // again the permission and directing to // the app setting } else if (Manifest.permission.WRITE_CONTACTS.equals(permission)) { showRationale(permission, R.string.permission_denied_contacts); // user did NOT check "never ask again" // this is a good place to explain the user // why you need the permission and ask if he wants // to accept it (the rationale) } else if ( /* possibly check more permissions...*/ ) { } } } } } 

您可以使用以下代码打开您的应用程序设置:

 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivityForResult(intent, REQUEST_PERMISSION_SETTING); 

没有办法将用户直接发送到授权页面。

你可以在你的onRequestPermissionsResult()检查shouldShowRequestPermissionRationale() onRequestPermissionsResult()

shouldShowRequestPermissionRationale https://youtu.be/C8lUdPVSzDk?t=2m23s

检查权限是否被授予或不在onRequestPermissionsResult() 。 如果没有,那么检查shouldShowRequestPermissionRationale()

  1. 如果此方法返回true则显示为什么需要此特定权限的解释。 然后再根据用户的select再requestPermissions()
  2. 如果它返回false则显示错误消息:未授予权限,应用程序无法继续进行或禁用特定function。

以下是示例代码。

 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case STORAGE_PERMISSION_REQUEST: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted :) downloadFile(); } else { // permission was not granted if (getActivity() == null) { return; } if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { showStoragePermissionRationale(); } else { Snackbar snackbar = Snackbar.make(getView(), getResources().getString(R.string.message_no_storage_permission_snackbar), Snackbar.LENGTH_LONG); snackbar.setAction(getResources().getString(R.string.settings), new View.OnClickListener() { @Override public void onClick(View v) { if (getActivity() == null) { return; } Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null); intent.setData(uri); OrderDetailFragment.this.startActivity(intent); } }); snackbar.show(); } } break; } } 

显然,谷歌地图正是这样做的位置权限。

这是检查当前许可状态的一个很好而简单的方法:

  @Retention(RetentionPolicy.SOURCE) @IntDef({GRANTED, DENIED, BLOCKED_OR_NEVER_ASKED }) public @interface PermissionStatus {} public static final int GRANTED = 0; public static final int DENIED = 1; public static final int BLOCKED_OR_NEVER_ASKED = 2; @PermissionStatus public static int getPermissionStatus(Activity activity, String androidPermissionName) { if(ContextCompat.checkSelfPermission(activity, androidPermissionName) != PackageManager.PERMISSION_GRANTED) { if(!ActivityCompat.shouldShowRequestPermissionRationale(activity, androidPermissionName)){ return BLOCKED_OR_NEVER_ASKED; } return DENIED; } return GRANTED; } 

警告:在用户通过用户提示(在sdk 23+设备上)接受/拒绝权限之前,返回BLOCKED_OR_NEVER_ASKED第一个应用程序的开始,

更新:

Android支持库现在也似乎有一个非常类似的类android.support.v4.content.PermissionChecker其中包含一个checkSelfPermission()返回:

 public static final int PERMISSION_GRANTED = 0; public static final int PERMISSION_DENIED = -1; public static final int PERMISSION_DENIED_APP_OP = -2; 

可能对某人有用: –

我注意到的是,如果我们检查onRequestPermissionsResult()callback方法中的shouldShowRequestPermissionRationale()标志,它只显示两种状态

状态1:返回true: – 任何时候用户点击拒绝权限(包括第一次)。

状态2:拒绝 – 如果用户select“不再询问”。

详细工作例子的链接

我有同样的问题,我想清楚了。 为了使生活更简单,我编写了一个util类来处理运行时权限。

 public class PermissionUtil { /* * Check if version is marshmallow and above. * Used in deciding to ask runtime permission * */ public static boolean shouldAskPermission() { return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M); } private static boolean shouldAskPermission(Context context, String permission){ if (shouldAskPermission()) { int permissionResult = ActivityCompat.checkSelfPermission(context, permission); if (permissionResult != PackageManager.PERMISSION_GRANTED) { return true; } } return false; } public static void checkPermission(Context context, String permission, PermissionAskListener listener){ /* * If permission is not granted * */ if (shouldAskPermission(context, permission)){ /* * If permission denied previously * */ if (((Activity)context).shouldShowRequestPermissionRationale(permission)) { listener.onPermissionPreviouslyDenied(); } else { /* * Permission denied or first time requested * */ if (PreferencesUtil.isFirstTimeAskingPermission(context, permission)) { PreferencesUtil.firstTimeAskingPermission(context, permission, false); listener.onPermissionAsk(); } else { /* * Handle the feature without permission or ask user to manually allow permission * */ listener.onPermissionDisabled(); } } } else { listener.onPermissionGranted(); } } /* * Callback on various cases on checking permission * * 1. Below M, runtime permission not needed. In that case onPermissionGranted() would be called. * If permission is already granted, onPermissionGranted() would be called. * * 2. Above M, if the permission is being asked first time onPermissionAsk() would be called. * * 3. Above M, if the permission is previously asked but not granted, onPermissionPreviouslyDenied() * would be called. * * 4. Above M, if the permission is disabled by device policy or the user checked "Never ask again" * check box on previous request permission, onPermissionDisabled() would be called. * */ public interface PermissionAskListener { /* * Callback to ask permission * */ void onPermissionAsk(); /* * Callback on permission denied * */ void onPermissionPreviouslyDenied(); /* * Callback on permission "Never show again" checked and denied * */ void onPermissionDisabled(); /* * Callback on permission granted * */ void onPermissionGranted(); } } 

PreferenceUtil方法如下。

 public static void firstTimeAskingPermission(Context context, String permission, boolean isFirstTime){ SharedPreferences sharedPreference = context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE; sharedPreference.edit().putBoolean(permission, isFirstTime).apply(); } public static boolean isFirstTimeAskingPermission(Context context, String permission){ return context.getSharedPreferences(PREFS_FILE_NAME, MODE_PRIVATE).getBoolean(permission, true); } 

现在,您只需要使用方法* checkPermission *和适当的参数。

这里是一个例子,

 PermissionUtil.checkPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE, new PermissionUtil.PermissionAskListener() { @Override public void onPermissionAsk() { ActivityCompat.requestPermissions( thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_EXTERNAL_STORAGE ); } @Override public void onPermissionPreviouslyDenied() { //show a dialog explaining permission and then request permission } @Override public void onPermissionDisabled() { Toast.makeText(context, "Permission Disabled.", Toast.LENGTH_SHORT).show(); } @Override public void onPermissionGranted() { readContacts(); } }); 

我的应用程序如何知道用户是否已经检查了“再也不问”?

如果用户select不再问 ,你会得到onPermissionDisabled的callback。

快乐编码:)

如果你想检测所有的“状态”(第一次被拒绝,刚刚被拒绝,刚刚被拒绝“永不再问”或被永久拒绝),你可以执行以下操作:

创build2个布尔值

 private boolean beforeClickPermissionRat; private boolean afterClickPermissionRat; 

请求权限之前设置第一个:

 beforeClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE); 

在你的onRequestPermissionsResult方法中设置第二个:

 afterClickPermissionRat = shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE); 

使用下面的“表”在onRequestPermissionsResult()中做任何你需要的事情(在检查你还没有权限之后):

 // before after // FALSE FALSE = Was denied permanently, still denied permanently --> App Settings // FALSE TRUE = First time deny, not denied permanently yet --> Nothing // TRUE FALSE = Just been permanently denied --> Changing my caption to "Go to app settings to edit permissions" // TRUE TRUE = Wasn't denied permanently, still not denied permanently --> Nothing 

可以通过检查是否在onRequestPermissionsResult()callback方法内显示权限基本原理 来确定它。 如果您发现任何权限设置为永不再问 ,则可以请求用户授予设置的权限。

我的完整实现将如下所示。 它适用于单个多个权限请求。 使用以下或直接使用我的图书馆。

 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(permissions.length == 0){ return; } boolean allPermissionsGranted = true; if(grantResults.length>0){ for(int grantResult: grantResults){ if(grantResult != PackageManager.PERMISSION_GRANTED){ allPermissionsGranted = false; break; } } } if(!allPermissionsGranted){ boolean somePermissionsForeverDenied = false; for(String permission: permissions){ if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){ //denied Log.e("denied", permission); }else{ if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){ //allowed Log.e("allowed", permission); } else{ //set to never ask again Log.e("set to never ask again", permission); somePermissionsForeverDenied = true; } } } if(somePermissionsForeverDenied){ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); alertDialogBuilder.setTitle("Permissions Required") .setMessage("You have forcefully denied some of the required permissions " + "for this action. Please open settings, go to permissions and allow them.") .setPositiveButton("Settings", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", getPackageName(), null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .setCancelable(false) .create() .show(); } } else { switch (requestCode) { //act according to the request code used while requesting the permission(s). } } } 

我在Android M中编写了权限请求的简写。此代码还处理向旧版Android的向后兼容性。

所有丑陋的代码都被提取到一个Fragment中,该Fragment将其自身附加到请求权限的Activity上。您可以使用PermissionRequestManager ,如下所示:

 new PermissionRequestManager() // We need a AppCompatActivity here, if you are not using support libraries you will have to slightly change // the PermissionReuqestManager class .withActivity(this) // List all permissions you need .withPermissions(android.Manifest.permission.CALL_PHONE, android.Manifest.permission.READ_CALENDAR) // This Runnable is called whenever the request was successfull .withSuccessHandler(new Runnable() { @Override public void run() { // Do something with your permissions! // This is called after the user has granted all // permissions, we are one a older platform where // the user does not need to grant permissions // manually, or all permissions are already granted } }) // Optional, called when the user did not grant all permissions .withFailureHandler(new Runnable() { @Override public void run() { // This is called if the user has rejected one or all of the requested permissions Le(this.getClass().getSimpleName(), "Unable to request permission"); } }) // After calling this, the user is prompted to grant the rights .request(); 

看看: https : //gist.github.com/crysxd/385b57d74045a8bd67c4110c34ab74aa

请不要把石头扔给我这个解决scheme。

这工作,但有点“哈克”。

当您调用requestPermissions ,请注册当前时间。

  mAskedPermissionTime = System.currentTimeMillis(); 

然后在onRequestPermissionsResult

如果结果没有被授予,请再次检查时间。

  if (System.currentTimeMillis() - mAskedPermissionTime < 100) 

由于用户确实无法在拒绝button上点击太快,所以我们知道他select了“不再询问”,因为callback是即时的。

使用风险自负。

方法shouldShowRequestPermissionRationale()可以是用户检查用户是否select了“从不再问”选项并且拒绝了该权限。 有很多的代码示例,所以我宁愿解释如何使用它的目的,因为我认为它的名字和它的实现使得它实际上更加复杂。

正如运行时请求权限所述,如果选项'永不再问'是可见的,则该方法返回true,否则返回false。 所以它在第一次显示对话框时返回false,然后从第二次返回true,并且只有当用户拒绝select该选项的权限时,那么它将再次返回false。

为了检测这种情况,可以检测出序列false-true-false,或者(更简单),你可以有一个标志,logging对话框显示的初始时间。 之后,该方法返回true或false,其中false将允许您检测何时select该选项。

我也想获得用户是否select“再也不问”的信息。 我用一面丑陋的国旗取得了“近乎解决”,但在我告诉你怎么做之前,我会告诉你我的动机:

我想最初提供权限引用function。 如果用户使用它并且没有权限,则他/她从上面或者从第二个和第三个获得第一个对话框。 当用户select“永不再问”时,我想禁用function并以不同的方式显示。 – 我的动作是由一个微调文本条目触发的,我也想给显示的标签文本加上'(Permission revoked)'。 这向用户显示:“有function,但由于我的权限设置,我无法使用它。 然而,这似乎是不可能的,因为我不能检查是否select了“再也不问”了。

我通过使用主动权限检查启用了我的function,从而达到了我可以接受的解决scheme。 我在onRequestPermissionsResult()中显示一个Toast消息,如果没有显示我的自定义理由popup窗口。 因此,如果用户select“永不再问”,他只会得到一个敬酒信息。 如果用户不愿意select“再也不问”,他只会得到操作系统popup的自定义原理和权限请求,而不是烤面包,因为连续的三个通知会太痛苦。

相反,当您在shouldShowRequestPermissionRationale()假条件下再次请求权限时,您将收到onRequestPermissionsResult()callback,作为PERMISSION_DENIED

从Android文档:

当系统要求用户授予权限时,用户可以select告诉系统不要再次请求该权限。 在这种情况下,任何时候应用程序使用requestPermissions()来再次请求该权限,系统立即拒绝该请求。 系统调用您的onRequestPermissionsResult()callback方法并传递PERMISSION_DENIED ,就像用户明确拒绝您的请求一样。 这意味着当你调用requestPermissions() ,你不能认为与用户发生了任何直接的交互。

我必须实现相机的dynamic权限。 如果发生三种可能的情况:1.允许,2.拒绝,3.不要再问。

  @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { for (String permission : permissions) { if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permission)) { //denied Log.e("denied", permission); } else { if (ActivityCompat.checkSelfPermission(getActivity(), permission) == PackageManager.PERMISSION_GRANTED) { //allowed Log.e("allowed", permission); } else { //set to never ask again Log.e("set to never ask again", permission); //do something here. } } } if (requestCode != MaterialBarcodeScanner.RC_HANDLE_CAMERA_PERM) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); return; } if (grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mScannerView.setResultHandler(this); mScannerView.startCamera(mCameraId); mScannerView.setFlash(mFlash); mScannerView.setAutoFocus(mAutoFocus); return; } else { //set to never ask again Log.e("set to never ask again", permissions[0]); } DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }; AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle("Error") .setMessage(R.string.no_camera_permission) .setPositiveButton(android.R.string.ok, listener) .show(); } private void insertDummyContactWrapper() { int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.CAMERA); if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_ASK_PERMISSIONS); return; } mScannerView.setResultHandler(this); mScannerView.startCamera(mCameraId); mScannerView.setFlash(mFlash); mScannerView.setAutoFocus(mAutoFocus); } private int checkSelfPermission(String camera) { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { return REQUEST_CODE_ASK_PERMISSIONS; } else { return REQUEST_NOT_CODE_ASK_PERMISSIONS; } } 

您可以使用if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)方法来检测是否永远不会检查是否被选中。

有关更多参考: 请检查

要检查多个权限使用:

  if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { showDialogOK("Service Permissions are required for this app", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: checkAndRequestPermissions(); break; case DialogInterface.BUTTON_NEGATIVE: // proceed with logic by disabling the related features or quit the app. finish(); break; } } }); } //permission is denied (and never ask again is checked) //shouldShowRequestPermissionRationale will return false else { explain("You need to give some mandatory permissions to continue. Do you want to go to app settings?"); // //proceed with logic by disabling the related features or quit the app. } 

explain()方法

 private void explain(String msg){ final android.support.v7.app.AlertDialog.Builder dialog = new android.support.v7.app.AlertDialog.Builder(this); dialog.setMessage(msg) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface paramDialogInterface, int paramInt) { // permissionsclass.requestPermission(type,code); startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.exampledemo.parsaniahardik.marshmallowpermission"))); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface paramDialogInterface, int paramInt) { finish(); } }); dialog.show(); } 

上面的代码也会显示对话框,它会将用户redirect到应用程序设置屏幕,如果已经检查过,他不会再询问button。

在上面的mVck的回答扩展,下面的逻辑确定是否已经检查了一个给定的许可请求“永不再问”:

 bool bStorage = grantResults[0] == Permission.Granted; bool bNeverAskForStorage = !bStorage && ( _bStorageRationaleBefore == true && _bStorageRationaleAfter == false || _bStorageRationaleBefore == false && _bStorageRationaleAfter == false ); 

这是从下面摘录(完整的例子看到这个答案 )

 private bool _bStorageRationaleBefore; private bool _bStorageRationaleAfter; private const int ANDROID_PERMISSION_REQUEST_CODE__SDCARD = 2; //private const int ANDROID_PERMISSION_REQUEST_CODE__CAMERA = 1; private const int ANDROID_PERMISSION_REQUEST_CODE__NONE = 0; public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults) { base.OnRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case ANDROID_PERMISSION_REQUEST_CODE__SDCARD: _bStorageRationaleAfter = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage); bool bStorage = grantResults[0] == Permission.Granted; bool bNeverAskForStorage = !bStorage && ( _bStorageRationaleBefore == true && _bStorageRationaleAfter == false || _bStorageRationaleBefore == false && _bStorageRationaleAfter == false ); break; } } private List<string> GetRequiredPermissions(out int requestCode) { // Android v6 requires explicit permission granting from user at runtime for security reasons requestCode = ANDROID_PERMISSION_REQUEST_CODE__NONE; // 0 List<string> requiredPermissions = new List<string>(); _bStorageRationaleBefore = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage); Permission writeExternalStoragePerm = ApplicationContext.CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage); //if(extStoragePerm == Permission.Denied) if (writeExternalStoragePerm != Permission.Granted) { requestCode |= ANDROID_PERMISSION_REQUEST_CODE__SDCARD; requiredPermissions.Add(Android.Manifest.Permission.WriteExternalStorage); } return requiredPermissions; } protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Android v6 requires explicit permission granting from user at runtime for security reasons int requestCode; List<string> requiredPermissions = GetRequiredPermissions(out requestCode); if (requiredPermissions != null && requiredPermissions.Count > 0) { if (requestCode >= ANDROID_PERMISSION_REQUEST_CODE__SDCARD) { _savedInstanceState = savedInstanceState; RequestPermissions(requiredPermissions.ToArray(), requestCode); return; } } } OnCreate2(savedInstanceState); } 
 public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case PERMISSIONS_REQUEST_EXTERNAL_STORAGE: { if (grantResults.length > 0) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { // Denied } else { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { // To what you want } else { // Bob never checked click } } } } } }