Android应用申请ACCESS_COARSE_LOCATION后仍报权限缺失错误怎么办
可能的原因
- 系统版本适配问题:如果你的应用
targetSdkVersion >= 31(Android 12及以上),系统对蓝牙权限做了重构,原有蓝牙权限+位置权限的组合已经不符合新系统的权限规则,会导致Nearby SDK误判权限缺失。 - 权限申请时机错误:
requestPermissions是异步调用,你在onStart中触发权限申请后立刻执行权限校验和接口调用,此时权限申请流程还未完成,就算用户之前已经授予过权限,也可能出现状态读取异常。 - 设备位置服务未开启:Android 6.0及以上系统中,就算应用已经拿到位置权限,只要用户关闭了系统全局的位置开关,Nearby Connections API也会抛出位置权限缺失的错误。
- 依赖库版本过旧:低版本的
play-services-nearby存在权限校验的已知bug,对新系统的权限规则适配不完善。
解决方案
- 适配不同系统版本的权限规则
首先更新AndroidManifest.xml的权限声明:
<!-- 原有基础权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- Android 12以下的位置权限要求 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <!-- Android 12+ 新增蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
动态申请权限时增加版本判断:
override fun onStart() { super.onStart() val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { arrayOf( Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_CONNECT ) } else { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ) } requestPermissions(requiredPermissions, REQUEST_CODE_PERMISSIONS) }
- 调整接口调用时机
不要在申请权限后立刻调用startDiscovery,将接口调用逻辑移到权限申请回调中,确认所有权限都被授予后再执行:
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_CODE_PERMISSIONS) { val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED } if (allGranted && isLocationEnabled()) { // 此处执行startDiscovery逻辑 } } }
- 增加位置开关校验
调用接口前先判断系统位置服务是否开启:
private fun isLocationEnabled(): Boolean { val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { locationManager.isLocationEnabled } else { locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) || locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) } }
- 升级依赖版本
将play-services-nearby升级到最新稳定版,避免已知bug:
dependencies { implementation 'com.google.android.gms:play-services-nearby:18.3.0' }
内容的提问来源于stack exchange,提问作者test_user
相关产品推荐
相关产品推荐

