Android Marshmallow:在 运行 时更改权限会导致应用程序崩溃

Android Marshmallow: Changing permissions at run time crashes app

Marshmallow 已重新设计获取权限。所以在调用需要权限的方法之前处理了权限并且它工作正常,但它在以下情况下崩溃:

第 1 步:打开应用并授予所有必要的权限

第 2 步:单击主页按钮(因此应用程序处于后台)

第 3 步:在设置中手动更改权限

第 4 步:从多任务启动应用程序,现在由于应用程序上下文变得无效而崩溃

观察到应用程序再次创建,不明白为什么会这样。欢迎任何纠正此问题的建议!

这是因为 Marshmallow 添加了额外的功能。您需要在运行时向用户请求。为此,请使用我制作的 class。然后在任何需要的地方使用它

public class AppPermission {

    public static boolean isMarshmallowPlusDevice() {
        return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1;
    }

    @TargetApi(Build.VERSION_CODES.M)
    public static boolean isPermissionRequestRequired(Activity activity, @NonNull String[] permissions, int requestCode) {
        if (isMarshmallowPlusDevice() && permissions.length > 0) {
            List<String> newPermissionList = new ArrayList<>();
            for (String permission : permissions) {
                if (PackageManager.PERMISSION_GRANTED != activity.checkSelfPermission(permission)) {
                    newPermissionList.add(permission);
                }
            }
            if (newPermissionList.size() > 0) {
                activity.requestPermissions(newPermissionList.toArray(new String[newPermissionList.size()]), requestCode);
                return true;
            }
        }
        return false;
    }
}

然后将此代码放在需要用户许可的地方。

if (!AppPermission.isPermissionRequestRequired(SignInActivity.this, new String[]{"android.permission.GET_ACCOUNTS"},
        REQUEST_APP_PERMISSION)) {
    // Your code if permission available
}

在此之后,在您的 FragmentActivity 中输入此代码 -

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case REQUEST_APP_PERMISSION:
            for (int i = 0; i < permissions.length; i++) {
                String permission = permissions[i];
                int grantResult = grantResults[i];
                switch (permission) {
                    case "android.permission.GET_ACCOUNTS":
                        if (PackageManager.PERMISSION_GRANTED == grantResult) {
                            // Your code
                        }
                        break;
                }
            }
            break;
    }
}

以上代码是为GET_ACCOUNTS申请权限,你可以改成任何需要的。

Observed that app gets created again, don't understand why this happens. Any suggestions to rectify this issue would be welcome!

因为当权限改变时,应用程序"state"应该失效。正确的做法是销毁根上下文,即应用程序本身。

每次查询需要这些权限的API方法时,您都必须检查权限授予状态。您不能依赖某些 SharedPreferences 标志来指示“ 用户已授予入职权限,好的,让我们玩得开心 ”。在这方面让你的应用程序无状态。

例如,您可以创建一些 BaseActivity/BaseFragment 或实用程序并将所有检查逻辑移到其中。

首先定义一个布尔值

 private boolean isPermissionGranted = false;

然后检查是否授予权限:

if (!isPermissionGranted) {
        checkPermission();
    }

运行时间权限检查的实际代码如下:

private void checkPermission() {
    int hasPermission = ContextCompat.checkSelfPermission(UserProfile.this, Manifest.permission.CAMERA);
    int hasWritePermission = ContextCompat.checkSelfPermission(UserProfile.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
    if (hasPermission != PackageManager.PERMISSION_GRANTED && hasWritePermission != PackageManager.PERMISSION_GRANTED) {
        if (!ActivityCompat.shouldShowRequestPermissionRationale(UserProfile.this, Manifest.permission.CAMERA) && !ActivityCompat.shouldShowRequestPermissionRationale(UserProfile.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            showMessage(getString(R.string.allow_access_to_camera_external_storage),
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ActivityCompat.requestPermissions(UserProfile.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                    REQUEST_CODE_ASK_PERMISSIONS);
                        }
                    });
            return;
        }
        ActivityCompat.requestPermissions(UserProfile.this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_CODE_ASK_PERMISSIONS);
        return;
    } else {
        isPermissionGranted = true;
    }
}

private void showMessage(String message, DialogInterface.OnClickListener       listener) {
    new AlertDialog.Builder(UserProfile.this)
            .setMessage(message)
            .setPositiveButton(R.string.ok, listener)
            .setNegativeButton(R.string.cancel, null)
            .create()
            .show();
}

  @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_ASK_PERMISSIONS:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                isPermissionGranted = true;

            } else {
                isPermissionGranted = false;
                Toast.makeText(UserProfile.this, R.string.permission_denied, Toast.LENGTH_SHORT)
                        .show();
            }
            break;

        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

您可以参考以上代码并在您的应用中实现。