checkSelfPermission 方法在 targetSdkVersion 22 中不起作用

checkSelfPermission method is not working in targetSdkVersion 22

CheckSelfPermission 方法未按预期工作,它在 android 6.0(Marshmallow) 中始终返回零。因为目标 sdk 是 22 并且我正在使用 http Client 进行网络连接。以下是代码片段。

private void insertDummyContactWrapper() {
    List<String> permissionsNeeded = new ArrayList<String>();

    final List<String> permissionsList = new ArrayList<String>();
    if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
        permissionsNeeded.add("GPS");
    if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
        permissionsNeeded.add("Read Contacts");
    if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
        permissionsNeeded.add("Write Contacts");

    if (permissionsList.size() > 0) {
        if (permissionsNeeded.size() > 0) {
            // Need Rationale
            String message = "You need to grant access to " + permissionsNeeded.get(0);
            for (int i = 1; i < permissionsNeeded.size(); i++)
                message = message + ", " + permissionsNeeded.get(i);
            showMessageOKCancel(message,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                                    REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
                        }
                    });
            return;
        }
        requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
        return;
    }

    insertDummyContact();
}

@TargetApi(Build.VERSION_CODES.M)
private boolean addPermission(List<String> permissionsList, String permission) {
    if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(permission);
        // Check for Rationale Option
        if (!shouldShowRequestPermissionRationale(permission)) return false;
    }
    return true;
}

private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
    new AlertDialog.Builder(MainActivity.this)
            .setMessage(message)
            .setPositiveButton("OK", okListener)
            .setNegativeButton("Cancel", null)
            .create()
            .show();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
            Map<String, Integer> perms = new HashMap<String, Integer>();
            // Initial
            perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
            // Fill with results
            for (int i = 0; i < permissions.length; i++)
                perms.put(permissions[i], grantResults[i]);
            // Check for ACCESS_FINE_LOCATION
            if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
                // All Permissions Granted
                insertDummyContact();
            } else {
                // Permission Denied
                Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)
                        .show();
            }
        }
        break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}"

方法 Context#checkSelfPermission(String) 已添加到 API 23。同样在 API 23 下面,它毫无意义,因为始终授予权限。在处理权限

之前检查 API 版本
private void insertDummyContactWrapper() {
    // the only way we insert the dummy contact if if we are below M.
    // Else we continue on and prompt the user for permissions
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        insertDummyContact();
        return;
    }

    List<String> permissionsNeeded = new ArrayList<String>();

    final List<String> permissionsList = new ArrayList<String>();
    if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
        permissionsNeeded.add("GPS");
    if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
        permissionsNeeded.add("Read Contacts");
    if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
        permissionsNeeded.add("Write Contacts");
    if (permissionsList.size() > 0) {
        if (permissionsNeeded.size() > 0) {
            // Need Rationale
            String message = "You need to grant access to " + permissionsNeeded.get(0);
            for (int i = 1; i < permissionsNeeded.size(); i++)
                message = message + ", " + permissionsNeeded.get(i);
            showMessageOKCancel(message,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                                    REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
                        }
                    });
            return;
        }
        requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
    }
}

参考:http://developer.android.com/reference/android/content/Context.html#checkSelfPermission(java.lang.String)

当以 23 之前的 API 级别为目标时,将应用兼容模式。旧的权限行为是 运行,即使在 运行 Android 设备上也是如此 6. 要使用新的权限系统,您必须针对 API 23(或将来更高) .

文档中指定了完整的行为:https://developer.android.com/training/permissions/requesting.html

  1. 如果您的应用程序针对 23 (Android M) 之前的 API 级别,则两者: ContextCompat#checkSelfPermission and Context#checkSelfPermission won't work and always return 0 (PERMISSION_GRANTED)。即使您 运行 Android 6.0 (API 23) 上的应用程序。

  2. 如果您将 API 级别定为 23 岁之前,那么您就不必考虑权限,这并不完全正确。如果您的应用程序的目标是 23 之前的 API 级别并且目标设备 Android 版本是:

    • Android < 6.0: 一切都会好的
    • Android 6.0: 应用程序的 运行-time 权限将默认授予(适用兼容模式),用户可以在Android设置中更改运行-时间权限,那么你可能会遇到问题。
  3. 正如我在第 1 点中所说,如果您在 Android 6.0 上将 API 级别定在 23 之前,那么 ContextCompat#checkSelfPermission and Context#checkSelfPermission 将不起作用。 幸运的是,您可以使用 PermissionChecker#checkSelfPermission 检查 运行 时间权限。

示例代码:

    public boolean selfPermissionGranted(String permission) {
        // For Android < Android M, self permissions are always granted.
        boolean result = true;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            
            if (targetSdkVersion >= Build.VERSION_CODES.M) {
                // targetSdkVersion >= Android M, we can
                // use Context#checkSelfPermission
                result = context.checkSelfPermission(permission)
                        == PackageManager.PERMISSION_GRANTED;
            } else {
                // targetSdkVersion < Android M, we have to use PermissionChecker
                result = PermissionChecker.checkSelfPermission(context, permission)
                        == PermissionChecker.PERMISSION_GRANTED;
            }
        }

        return result;
    }

要获取目标 Sdk 版本,您可以使用:

    try {
        final PackageInfo info = context.getPackageManager().getPackageInfo(
                context.getPackageName(), 0);
        targetSdkVersion = info.applicationInfo.targetSdkVersion;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }

它适用于 Android M 的 Nexus 5。