无法拦截用户拒绝棉花糖的许可

时间:2015-11-15 19:24:45

标签: android permissions android-6.0-marshmallow

我当前的应用程序有一个FeedbackFragment,它使用支持库中的Fragment并提供一个复选框,允许用户选择性地发送带有反馈的系统日志。由于将日志附加到外发电子邮件需要访问外部存储(WRITE_EXTERNAL_STORAGE权限),因此我必须在要求FeedbackFragment时请求许可。如果用户拒绝写入外部存储的权限,我想禁用/隐藏“包含系统日志”#39;复选框,但我希望此屏幕的其余功能正常工作(在Marshmallow设备上工作正常,BTW)。我已经根据官方Android文档编写了相应的方法,以及许多SO文章的组合,这就是我目前所拥有的。请注意,我并没有停留在“拒绝”的任何断点处。这段代码中的分支。

以下所有逻辑都是在checkExternalStoragePermissions()

onCreateView()来电中创建的

我错过了什么?

private void checkExternalStoragePermissions() {
    if (ContextCompat.checkSelfPermission(getContext(), WRITE_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
        canSendAttachments = true;
        systemLogsCheckbox.setEnabled(true);
    } else {
        requestExternalStoragePermission();
    }

}

private void requestExternalStoragePermission() {
    if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), WRITE_EXTERNAL_STORAGE)) {

        new SnackBar.Builder(getActivity())
                .withMessage(getString(R.string.write_external_storage_permission_rationale))
                .withDuration(SnackBar.PERMANENT_SNACK)
                .withActionMessage("OK")
                .withOnClickListener(new SnackBar.OnMessageClickListener() {
                    @Override
                    public void onMessageClick(Parcelable token) {
                        ActivityCompat.requestPermissions(getActivity(),
                                new String[]{WRITE_EXTERNAL_STORAGE},
                                WRITE_TO_EXTERNAL_STORAGE_PERMISSION);
                    }
                })
                .withTextColorId(R.color.almanac_red_tab_highlight)
                .show();

    } else {

        ActivityCompat.requestPermissions(getActivity(),
                new String[]{WRITE_EXTERNAL_STORAGE}, WRITE_TO_EXTERNAL_STORAGE_PERMISSION);
    }

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
                                       @NonNull int[] grantResults) {
    if (requestCode == WRITE_TO_EXTERNAL_STORAGE_PERMISSION) {
        if ((grantResults.length == 1) && (grantResults[0] == PERMISSION_GRANTED)) {

            canSendAttachments = true;
            systemLogsCheckbox.setEnabled(true);
        } else {
            canSendAttachments = false;
            systemLogsCheckbox.setEnabled(false);
            systemLogsCheckbox.setChecked(false);
        }
    } else
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

3 个答案:

答案 0 :(得分:2)

如果您使用Fragment拨打电话,则应致电FragmentCompat.requestPermissions,以便回调路由您的片段而不是您的活动。

您可能需要将此文件添加到gradle文件中,因为FragmentCompat位于support-v13 lib中。

compile 'com.android.support:support-v13:23.1.1'

答案 1 :(得分:0)

首先,您需要在OnRequestPermissionsResultCallback中实施Listener类的ActivityCompat Activity并覆盖void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)方法,以检查用户是否允许或拒绝该权限

你可以这样做:

int REQUEST_STORAGE = 1;

private void checkExternalStoragePermissions() {
    if (hasStoragePermissionGranted()) {
        canSendAttachments = true;
        systemLogsCheckbox.setEnabled(true);
    } else {
        requestExternalStoragePermission();
    }
}

public boolean hasStoragePermissionGranted(){
        return  ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}

public void requestExternalStoragePermission() {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        ActivityCompat.requestPermissions(MainActivity.this, {Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_STORAGE);
    }
}

当用户允许或拒绝来自运行时权限对话框的权限时,将调用onRequestPermissionsResult()方法。

您还可以处理用户选中时从未显示“运行时权限”对话框的情况。

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

希望它对你有所帮助。

答案 2 :(得分:0)

虽然 @iagreen 的答案很接近,但我最初遇到的问题是因为我在代码中使用了ActivityCompat版本的相应方法。一旦我从方法调用中删除了该前缀并使用了Fragment类中的相应方法,一切都按照我现在的预期进行,原始问题已经解决。

话虽如此,我也在研究如何使用ContentProvider来完全否定WRITE_EXTERNAL_STORAGE权限的需要,正如 @Chris Stratton 所建议的那样