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

如果用户拒绝一个重要的权限,在我看来,应用程序应该显示一个解释为什么需要权限和什么影响拒绝。该对话框有两个选项:

重试(再次请求许可) 拒绝(应用程序将工作没有该许可)。

但是,如果用户选中“Never ask again”,则不应该显示带有解释的第二个对话框,特别是如果用户之前已经拒绝了一次。 现在的问题是:我的应用程序如何知道用户是否选中了Never ask again?IMO onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)没有给我这个信息。

第二个问题是:谷歌是否计划在权限对话框中包含一个自定义消息,以解释为什么应用程序需要权限?这样就不会出现第二个对话框,这肯定会带来更好的用户体验。


当前回答

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

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

没有“永不再次显示”复选框(不像开发人员预览1)。如果用户拒绝权限,如果权限是必不可少的应用程序,它可以显示另一个对话框来解释应用程序请求该权限的原因,例如:

如果用户再次拒绝,应用程序应该关闭(如果它绝对需要该权限)或继续运行有限的功能。如果用户重新考虑(并选择重试),则再次请求权限。这次的提示符是这样的:

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

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

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

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.

要知道用户是否拒绝了“never ask again”,你可以再次检查你的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);

无法将用户直接发送到授权页面。

其他回答

shouldShowRequestPermissionRationale根据之前权限请求中的用户首选项返回true或false。

如果用户只是拒绝权限(不是永远)shouldShowRequestPermissionRationale将返回true。如果永远拒绝许可,则返回false。窍门是即使用户允许了权限shouldShowRequestPermissionRationale也会返回false。

因此,我们可以结合这两个条件来得到永不再问的选择与否。

因此,如果用户不允许权限,并且shouldShowRequestPermissionRationale返回false,那么这意味着用户选择永远不会再次请求权限。

https://stackoverflow.com/a/58114769/5151336

对每一种许可情况的完整解释

/**
 *    Case 1: User doesn't have permission
 *    Case 2: User has permission
 *
 *    Case 3: User has never seen the permission Dialog
 *    Case 4: User has denied permission once but he din't clicked on "Never Show again" check box
 *    Case 5: User denied the permission and also clicked on the "Never Show again" check box.
 *    Case 6: User has allowed the permission
 *
 */
public void handlePermission() {
    if (ContextCompat.checkSelfPermission(MainActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        // This is Case 1. Now we need to check further if permission was shown before or not

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

            // This is Case 4.
        } else {
            // This is Case 3. Request for permission here
        }

    } else {
        // This is Case 2. You have permission now you can do anything related to it
    }
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // This is Case 2 (Permission is now granted)
    } else {
        // This is Case 1 again as Permission is not granted by user

        //Now further we check if used denied permanently or not
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // case 4 User has denied permission but not permanently

        } else {
            // case 5. Permission denied permanently.
            // You can open Permission setting's page from here now.
        }

    }
}

我还想知道用户是否选择了“never ask again”。我已经实现了一个“几乎解决方案”与一个丑陋的旗帜,但在我告诉你如何,我将告诉你我的动机:

I would like to offer the permission referring functionality initially. If the user uses it and has no rights, he/she gets the either the 1th dialog from above or both the 2nd and 3rd. When the user has chosen 'Never ask again' I would like to disable the functionality and to display it differently. - My action is triggered by a spinner text entry, I would also like to add '(Permission revoked)' to the label text displayed. This shows to the user: 'There is functionality but I cannot use it, due to my permission settings.' However, this does not seem to be possible, as I cannot check whether or not 'Never ask again' has been chosen.

I came to a solution I can live with by having my functionality always enabled with an active permission check. I am showing a Toast message in onRequestPermissionsResult() in case of a negative response but only if I have not shown my custom rationale popup. So if the user has chosen 'Never ask again' he gets a toast message only. If the user is reluctant to chose 'never ask again' he gets only the custom rationale and the permission request popup by the operation system but not toast, as three notifications in a row would be too much pain.

在阅读了一些答案后,我发现了许多冗长而令人困惑的答案 我的结论是

if (!ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_EXTERNAL_STORAGE))
                Toast.makeText(this, "permanently denied", Toast.LENGTH_SHORT).show();

您可以使用if (ActivityCompat。shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)方法来检测never ask是否被检查。

更多参考:检查这个

检查是否使用了多个权限:

  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.
                        }

解释()方法

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();
    }

上面的代码还将显示对话框,这将重定向到用户的应用程序设置屏幕,在那里他可以给予权限,如果选中了“永不再问”按钮。