二级权限请求永远不会出现

secondary permission request is never presented

这是我原来的 post 的重写,因为我发现,与权限概述相反:

因此,如果我单击拒绝,我将永远不会允许日历权限。

我在清单中设置权限:

<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>

开始时,我检查 MainActivity 中的日历权限,因为用户通过我的应用程序添加约会并使它们可用于 Google 日历是必需的(如果我允许,我的应用程序添加日历):

    AccessCalendar accessCalendar = new AccessCalendar();
    if(accessCalendar.requestCalendarPermissions(mContext, this)){
        /**
         * calendar read and write permissions not allowed: explain why needed
         */
        Log.d(TAG, "calendar read and write permissions not allowed: explain why needed");
        ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.constraintLayout);
        Snackbar.make(constraintLayout, R.string.write_calendar_permission_explanation, Snackbar.LENGTH_LONG).show();
        DialogFragment permissionDialog = new CalendarPermissionExplanationFragment();
        try {
            permissionDialog.show(getSupportFragmentManager(), "CalendarPermissionExplanationFragment");
        }catch (Exception e){
            Log.d(TAG, "exception e is: " + e);
        }

    }else{
        /**
         * calendar read and write permissions allowed! No need to explain
         */
        Log.d(TAG, "calendar read and write permissions allowed! No need to explain");
    }

AccessCalendar.requestCalendarPermissions 是(几乎抄袭自请求应用程序权限):

public boolean requestCalendarPermissions(Context context, Activity activity){
    Log.d(TAG, "Entered: requestCalendarPermissions");
    boolean explain = false;
    if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CALENDAR)
            != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(context,
            Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED ) {
        // Permission is not granted
        Log.d(TAG, "read and write permission not granted");
        if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
                Manifest.permission.READ_CALENDAR) &&
                ActivityCompat.shouldShowRequestPermissionRationale(activity,
                Manifest.permission.WRITE_CALENDAR)) {
            Log.d(TAG, "shouldShowRequestPermissionRationale is true");
            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
            Toast.makeText(context, R.string.write_calendar_permission_explanation, Toast.LENGTH_LONG).show();
            explain = true;
        } else {
            Log.d(TAG, "shouldShowRequestPermissionRationale is false");
            // No explanation needed; request the permission
            ActivityCompat.requestPermissions(activity,
                    new String[]{Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR},
                    MY_PERMISSIONS_REQUEST_CALENDAR);
            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    }else{
        //permission is granted, so set permission to true
        Log.d(TAG, "read and write calendar permissions granted");
    }
    return explain;
}

由于一些问题,我不得不使用Toast来提供解释。我现在看到初始权限对话框,谁的请求尝试,拒绝或允许,由 MainActivity.onRequestPermissionsResult():

处理
public void onRequestPermissionsResult(int requestCode,
                                       String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    Log.d(TAG, "Entered: onRequestPermissionsResult");
    Log.d(TAG, "requestCode is: " + requestCode);
    Log.d(TAG, "permissions is: " + permissions);
    Log.d(TAG, "grantResults is: " + grantResults);
    int cntPermissions = grantResults.length;
    if(cntPermissions > 0) {
        for (int i = 0; i < cntPermissions; i++) {
            Log.d(TAG, "permissions[" + i + "] is: " + permissions[i]);
        }
    }
    int cntGrantResults = grantResults.length;
    if(cntGrantResults > 0) {
        for (int i = 0; i < cntGrantResults; i++) {
            Log.d(TAG, "grantResults[" + i + "] is: " + grantResults[i]);
        }
    }
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_CALENDAR:
            Log.d(TAG, "Entered: case MY_PERMISSIONS_REQUEST_CALENDAR");
            if(cntPermissions > 0) {
                if(permissions[1].equals("android.permission.WRITE_CALENDAR") && grantResults[1] == 0){
                    Toast.makeText(this, R.string.write_calendar_permission, Toast.LENGTH_LONG).show();
                    AccessCalendar accessCalendar = new AccessCalendar();
                    accessCalendar.createCalendar(mContext, this);
                    //get calendar information again to see if petrecords calendar was created
                    Log.d(TAG, "get the calendars in the system to see if petrecords now exists");
                    accessCalendar.getCalendars(mContext, this);
                }else{
                    Toast.makeText(this, R.string.error_no_write_calendar_permission, Toast.LENGTH_LONG).show();
                    Log.d(TAG, "create alertdialog to explain why the permission is required");
                }
            }else{
                Log.d(TAG, "no permissions returned");
            }
            break;
        default:
            Log.d(TAG, "illegal requestCode value");
            break;
    }
    return;
}

在这种情况下,将创建一个新日历。否则,用户在拒绝后继续。稍后,用户会看到约会,此时可能希望通过我的应用程序添加约会,因此单击约会选项卡,然后单击管理约会按钮。此时,输入完全相同的代码以检查日历权限,如上所示。

那时我希望看到二级权限对话框,但没有,我得到的只是我的解释。我也希望在最初拒绝后重新启动我的应用程序时看到二级权限对话框,但没有。

那么,为什么 Android 不显示二级权限对话框?

shouldShowRequestPermissionRationale() 方法表示权限之前被拒绝,您应该解释为什么要请求权限。

为此,您应该使用 DialogSnackbar 以及用户可以用来再次触发权限请求的操作。

如果您的应用在没有此权限的情况下无法运行,您可能需要显示更大的屏幕来说明该应用在没有此权限的情况下无法运行。

您甚至可以忽略 shouldShowRequestPermissionRationale() 标志,只是一次又一次地显示权限请求。不过这很烦人。