Android 动态检查是否拥有某项权限的最佳实践
API Level 23 的 ContextCompact.checkSelfPermission() 在 小于 23 时,永远返回 PERMISSION_GRANTED
在 API Level = 23 时,ContextCompact.checkSelfPermission() 才返回正确的值
如果 targetAPI Level 在 23 以前,但是又要支持23,使用 PermissionChecker.checkSelfPermission() 是最靠谱的,
这个 PermissionChecker support-v4 lib 里新出的API
需要 在build.gradle 里
compile ‘com.android.support:support-v4:23.1.1’
注意版本号,版本号较低的没有这个API
首先检查是否在安装时申请并授予了指定权限,如果没有再查询AppOps是否是在安装后被用户使用AppOps revoke 了权限。
如果没有记错的话,这个 AppOps 是android官方在4.3的时候引进的一个权限管理模块,可能后来觉得不好就给干掉了
然而现在在23上使用 PermissionChecker 检查的AppOps的结果和 实际的 “Runtime Permission”的权限授予结果一致,说明android在6.0上搞的所谓新权限机制”Runtime Permission” 本来就是复活了的 AppOps
/**
* Checks whether your app has a given permission and whether the app op
* that corresponds to this permission is allowed.
*
* @param context Context for accessing resources.
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
*/
public static int checkSelfPermission(@NonNull Context context,
@NonNull String permission) {
return checkPermission(context, permission, android.os.Process.myPid(),
android.os.Process.myUid(), context.getPackageName());
}
/**
* Checks whether a given package in a UID and PID has a given permission
* and whether the app op that corresponds to this permission is allowed.
*
* @param context Context for accessing resources.
* @param permission The permission to check.
* @param pid The process id for which to check.
* @param uid The uid for which to check.
* @param packageName The package name for which to check. If null the
* the first package for the calling UID will be used.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
*/
public static int checkPermission(@NonNull Context context, @NonNull String permission,
int pid, int uid, String packageName) {
if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
return PERMISSION_DENIED;
}
String op = AppOpsManagerCompat.permissionToOp(permission);
if (op == null) {
return PERMISSION_GRANTED;
}
if (packageName == null) {
String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
if (packageNames == null || packageNames.length <= 0) {
return PERMISSION_DENIED;
}
packageName = packageNames[0];
}
if (AppOpsManagerCompat.noteProxyOp(context, op, packageName)
!= AppOpsManagerCompat.MODE_ALLOWED) {
return PERMISSION_DENIED_APP_OP;
}
return PERMISSION_GRANTED;
}
EOF.
Written on October 9, 2016
Written on October 9, 2016
转载请联系我,微信号: michaelzhoujay