Android单权限请求正常,多权限请求无UI弹窗问题求助
问题描述
我正尝试按照官方文档向用户申请精确定位追踪权限。测试代码时发现,单权限请求可正常弹出授权UI,但申请多权限(ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION、后台定位权限)时,授权UI完全不显示。两者代码几乎一致,具体多权限请求代码如下:
private fun requestPermissions() { val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions() ) { granted -> Timber.tag("ASDASD").e(granted.toString()) // 检查是否已授予精确或大致位置权限 } if (TrackingUtility.hasLocationPermissions(requireContext())) { return } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { requestPermissionLauncher.launch( arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ) ) } else { requestPermissionLauncher.launch( arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION ) ) } }
截图情况:
- 单权限请求正常显示授权UI
- 多权限请求无UI弹窗
我严格遵循文档操作,但只有使用SingleRequestPermission时才能正常工作,请问这是什么原因?
解决方案
这个问题的核心原因是Android 10(API 29)及以上版本对后台定位权限的申请有严格的顺序要求:必须先获得前台定位权限(ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION),才能申请后台定位权限ACCESS_BACKGROUND_LOCATION,不能将前台权限和后台权限放在同一次请求中批量申请。
具体修正步骤:
- 先发起前台定位权限(
ACCESS_FINE_LOCATION+ACCESS_COARSE_LOCATION)的申请,确保用户授予其中至少一个。 - 只有当前台权限已被授予后,再单独发起
ACCESS_BACKGROUND_LOCATION权限的申请。
修改后的代码示例:
private val foregroundLocationLauncher = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions() ) { results -> val hasForegroundPermission = results.any { it.value } if (hasForegroundPermission) { // 前台权限已授予,申请后台定位权限 requestBackgroundLocationPermission() } } private val backgroundLocationLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { granted -> Timber.tag("ASDASD").e("后台定位权限是否授予:$granted") } private fun requestPermissions() { if (TrackingUtility.hasLocationPermissions(requireContext())) { return } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { foregroundLocationLauncher.launch( arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ) ) } else { // 先检查前台权限是否已授予 val hasForegroundPermission = ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED if (!hasForegroundPermission) { // 先申请前台权限 foregroundLocationLauncher.launch( arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ) ) } else { // 直接申请后台权限 requestBackgroundLocationPermission() } } } private fun requestBackgroundLocationPermission() { backgroundLocationLauncher.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION) }
额外注意事项:
- 必须在
AndroidManifest.xml中声明所有需要的权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="32" /> <!-- Android 13+ 需单独申请POST_NOTIFICATIONS权限才能使用后台定位 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
- Android 13(API 33)及以上版本,后台定位权限还依赖
POST_NOTIFICATIONS权限,需要先授予通知权限才能申请后台定位。
内容的提问来源于stack exchange,提问作者isilvani
相关产品推荐
相关产品推荐

