Kotlin调用FusedLocationProviderClient获取位置返回null问题排查
问题原因分析
从日志可以确认位置权限已经正常授予,返回location=null的核心原因如下:
FusedLocationProviderClient.lastLocation接口本身仅读取系统缓存的历史位置记录,不会主动触发定位。当设备满足以下任意一种情况时,缓存为空就会返回null:- 设备刚重启完成,还没有任何应用触发过定位
- 系统位置服务刚被手动开启,还未生成过位置缓存
- 设备的定位缓存被系统主动清除
- 额外排查点:确认设备的全局位置开关(下拉状态栏的定位按钮)已经开启,仅授予应用位置权限但关闭系统全局定位也会返回null
解决方案
方案1:优先检查并引导开启系统位置服务
增加位置服务可用性检查逻辑,未开启时跳转到系统设置页引导用户开启。
方案2:主动请求实时位置更新替代仅读取缓存
不要完全依赖lastLocation接口,主动触发一次实时定位,拿到有效位置后再停止定位即可,示例修改代码如下:
首先确保app模块的build.gradle已添加位置服务依赖:
dependencies { implementation 'com.google.android.gms:play-services-location:21.0.1' }
修改后的Activity代码示例:
class MainActivity : AppCompatActivity() { private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var text: TextView // 定位请求配置 private val locationRequest = LocationRequest.create().apply { interval = 10000 fastestInterval = 5000 priority = LocationRequest.PRIORITY_HIGH_ACCURACY numUpdates = 1 // 只请求一次定位结果 } // 定位结果回调 private val locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { super.onLocationResult(locationResult) val location = locationResult.lastLocation if (location != null) { text.text = "My location ${location.latitude}, ${location.longitude}" // 拿到结果后停止定位节省资源 fusedLocationClient.removeLocationUpdates(this) } else { text.text = "location = null" } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) text = findViewById(R.id.textView) val button: Button = findViewById(R.id.button) fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) val requestMultiplePermissions = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions()) { permissions -> permissions.entries.forEach { Log.e("DEBUG", "${it.key} = ${it.value}") } } button.setOnClickListener { requestLocation() } requestMultiplePermissions.launch( arrayOf( Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION ) ) } private fun requestLocation() { if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { text.text = "do not grants the permission" return } // 先尝试读取缓存,缓存为空再主动请求实时定位 fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? -> if (location != null) { text.text = "My location ${location.latitude}, ${location.longitude}" } else { // 缓存为空,触发实时定位 fusedLocationClient.requestLocationUpdates( locationRequest, locationCallback, Looper.getMainLooper() ) } } } override fun onDestroy() { super.onDestroy() // 页面销毁时移除定位回调避免内存泄漏 fusedLocationClient.removeLocationUpdates(locationCallback) } }
内容的提问来源于stack exchange,提问作者Andrew07
相关产品推荐
相关产品推荐

