You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FusedLocationProviderClient时,「每次询问」权限下仅单次采集位置数据问题

「每次询问」权限模式下FusedLocationProviderClient位置采集问题的解决办法

问题根源

「每次询问」权限是Android的临时授权模式,授权仅对单次位置请求有效。FusedLocationProviderClient的持续更新请求不会自动触发二次授权弹窗,且系统权限检查会误返回PERMISSION_GRANTED,导致后续请求静默失败;另外,登出时未彻底清理客户端实例和缓存,导致复用了首次授权的旧位置数据。

具体修复方案

1. 每次采集前主动校验并触发授权

不要只依赖checkSelfPermission的结果,结合shouldShowRequestPermissionRationale判断是否需要再次请求授权(即使权限检查显示已授予):

fun startLocationCollection() {
    val hasPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
    if (!hasPermission) {
        ActivityCompat.requestPermissions(...)
        return
    }

    // 针对「每次询问」模式,主动触发二次授权提示
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
        // 弹出自定义弹窗告知用户需要再次授权,然后重新发起权限请求
        showPermissionPromptDialog {
            ActivityCompat.requestPermissions(...)
        }
        return
    }

    // 正式发起位置更新请求
    fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
}

2. 登出时彻底清理位置客户端状态

登出时不仅要移除回调,还要清除缓存并销毁客户端实例,避免复用旧状态:

fun onUserLogout() {
    fusedLocationProviderClient?.removeLocationUpdates(locationCallback)
    fusedLocationProviderClient?.flushLocations() // 清空位置缓存
    fusedLocationProviderClient = null // 销毁实例
}

3. 监听权限变更事件

注册广播监听权限状态变化,当用户在系统设置中修改权限后,自动调整采集逻辑:

private val permissionChangeReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        intent?.takeIf { it.action == Intent.ACTION_PERMISSION_CHANGED }?.let {
            val changedPermission = it.getStringExtra(Intent.EXTRA_PERMISSION_NAME)
            if (changedPermission == Manifest.permission.ACCESS_FINE_LOCATION) {
                // 根据新权限状态重启或停止采集
                adjustLocationCollection()
            }
        }
    }
}

// 在Service的onCreate中注册
registerReceiver(permissionChangeReceiver, IntentFilter(Intent.ACTION_PERMISSION_CHANGED))
// 在Service的onDestroy中注销
unregisterReceiver(permissionChangeReceiver)

4. 登录时重置位置缓存

登录成功后,先清空缓存再发起采集请求,确保获取最新位置:

fun onUserLoginSuccess() {
    fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
    fusedLocationProviderClient.flushLocations()
    startLocationCollection()
}

关于是否为FusedLocationProviderClient的Bug

这不是官方Bug,属于「每次询问」权限模式的设计特性。官方文档中描述的“正常工作”针对的是持续授权场景,而临时授权模式需要开发者主动处理重复授权的逻辑,系统不会自动触发后续的授权弹窗。

内容的提问来源于stack exchange,提问作者Nelson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:41:09