
Android 6.0(API 23)之前,位置等危险权限在安装时即被系统一次性授予,无运行时动态控制能力,因此 checkSelfPermission 在 API 21/22 上恒返回 PERMISSION_GRANTED,与用户是否点击对话框无关。
android 6.0(api 23)之前,位置等危险权限在安装时即被系统一次性授予,无运行时动态控制能力,因此 `checkselfpermission` 在 api 21/22 上恒返回 `permission_granted`,与用户是否点击对话框无关。
在 Android 系统演进中,权限模型存在根本性分水岭:API 23(Android 6.0 Marshmallow)是运行时权限(Runtime Permissions)的起始版本。在此之前(包括 API 21 Lollipop 和 API 22),所有 <uses-permission></uses-permission> 声明的权限(如 ACCESS_FINE_LOCATION、READ_EXTERNAL_STORAGE 等)均属于“安装时权限”(Install-time permissions)。系统在应用安装阶段即完成全部权限授予,用户无法在运行时撤销或拒绝单个权限——这意味着:
- 调用
ContextCompat.checkSelfPermission()或PermissionChecker.checkSelfPermission()永远返回PackageManager.PERMISSION_GRANTED(只要该权限已声明于AndroidManifest.xml中); -
ActivityCompat.shouldShowRequestPermissionRationale()恒为false(因从未存在过“拒绝后再次请求”的语义); -
requestPermissions()方法虽可调用,但实际不会弹出任何权限对话框,仅触发回调(如onRequestPermissionsResult),且结果始终为GRANTED。
因此,你在 API 21 设备上观察到的 Log.d("request_Permission 21:", "has been granted!") 并非逻辑错误,而是符合历史设计的事实行为。此时所谓“权限对话框出现”,实为你的自定义 PermissionDialog.showForResult(...) 手动弹出(与系统无关),而 checkSelfPermission 的返回值早已确定,与 UI 状态完全解耦。
✅ 正确的兼容性处理应遵循以下原则:
-
按 SDK 版本分流逻辑:
- API ≥ 23:走标准运行时权限流程(
requestPermissions+onRequestPermissionsResult); - API 跳过所有运行时检查与请求逻辑,直接执行定位功能(因权限必已授予);
- API ≥ 23:走标准运行时权限流程(
避免冗余判断:
不应在 API 21/22 中调用shouldShowRequestPermissionRationale或尝试“请求”权限——既无效,也易引发混淆。
示例修正代码(Kotlin 风格,推荐使用 ActivityResultLauncher):
private val locationPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) {
startLocationUpdates() // ✅ 安全执行
} else {
showPermissionDeniedHint()
}
}
fun requestLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
} else {
// API <p>⚠️ 注意事项:</p>
- 不要为 API 21/22 实现“模拟运行时权限”的逻辑(如弹窗+假校验),这违背平台契约,且导致行为不一致;
-
PermissionChecker是旧版 Support Library 提供的兼容工具,仅用于低版本兜底,不应替代ContextCompat.checkSelfPermission,更不可用于判断 API 23 前的“真实授权状态”(因其本质就是恒真); - 若目标 SDK ≥ 31(Android 12),还需额外适配大致位置(Approximate Location) 新特性,区分
ACCESS_FINE_LOCATION与ACCESS_COARSE_LOCATION的用户选择粒度。
总结:API 21/22 的 checkSelfPermission 恒为 GRANTED,不是 Bug,而是 Android 权限模型演进的历史必然。开发者需以版本为纲,精准分流,方能写出健壮、可维护的位置权限逻辑。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











