我应该更喜欢 ContextCompat 还是 PermissionChecker 来检查 Android 上的权限?

Should I prefer ContextCompat or PermissionChecker for permission checking on Android?

我可以选择以下任一方法来检查我的应用程序是否具有给定权限。

首选哪一个?

ContextCompat(来自 support-compat 库):

ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)

PermissionChecker(来自support-core-utils库):

PermissionChecker.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)

请注意(自 25.3.1 起)-core-utils 取决于 -compat:

| | +--- com.android.support:support-core-utils:25.3.1 | | | +--- com.android.support:support-annotations:25.3.1 | | | \--- com.android.support:support-compat:25.3.1 (*)

我会选择 ContextCompat 因为可用的文档和教程质量
但我在某处读到以下内容:
如果你的设备是 运行 Android M 及更高版本并且 targetSdkVersion 低于 22,则两者之间存在细微差别。
当您在设备权限设置为关闭的情况下首次启动应用程序时,行为如下:

  1. ContextCompat:始终returns已授权
  2. 权限检查器:Returns 已授予或 PERMISSION_DENIED_APP_OP

使用 PermissionChecker 可能更明智,但同样要实现运行时权限,您需要将 targetSdkVersion 设置为 23 或更高。

进入 PermissionChecker 的源代码,我们可以看到它首先调用 Context#checkPermission and bails early if the calling code does not have permission. If the calling code does have permission it then goes to the mysterious AppOpsManager asking if we have permissionToOp, followed by a check against the return of noteProxyOp。这给了我们关于此方法的用途的提示,因为 noteProxyOp 的文档以:

开头

Make note of an application performing an operation on behalf of another application when handling an IPC.

此外,如果我们检查 PermissionChecker 方法的 return 值,我们会看到我们得到了 3 个可能结果之一:

The permission check result which is either PERMISSION_GRANTED or PERMISSION_DENIED or PERMISSION_DENIED_APP_OP.

即 0、-1 或 -2 return 值。此 class 似乎旨在供接收进程间通信并代表其他应用执行操作的应用使用。

ContextCompat 另一方面,简单地获取当前进程 ID 并直接 returns Context#checkPermission:

的结果

PERMISSION_GRANTED if the given pid/uid is allowed that permission, or PERMISSION_DENIED if it is not.

因此对于大多数编写标准 Android 应用程序的开发人员来说,使用 ContextCompat