Jetpack Compose中如何用FusedLocationProviderClient单次查询位置?
在Jetpack Compose中实现单次定位查询
方法一:直接使用getCurrentLocation(推荐)
Google Play Services Location库提供了getCurrentLocation方法,专门用于获取单次位置,无需手动管理监听注销。结合协程能在Compose中更优雅地实现:
首先初始化FusedLocationProviderClient:
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
然后在Compose的协程作用域(比如LaunchedEffect)中调用:
LaunchedEffect(Unit) { val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_HIGH_ACCURACY timeoutMillis = 10000 // 设置10秒超时 } // 先检查定位权限 if (ContextCompat.checkSelfPermission( context, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) { try { // 用suspendCoroutine包装Task,避免回调嵌套 val location = suspendCoroutine<Location?> { cont -> fusedLocationClient.getCurrentLocation( locationRequest, null // 无需LocationSettingsRequest可传null,按需添加 ).addOnSuccessListener { loc -> cont.resume(loc) }.addOnFailureListener { e -> cont.resumeWithException(e) } } location?.let { // 处理获取到的单次位置 Log.d("Location", "单次定位成功:${it.latitude}, ${it.longitude}") } ?: run { Log.d("Location", "未获取到有效位置") } } catch (e: Exception) { Log.e("Location", "定位失败", e) } } }
如果引入kotlinx-coroutines-play-services依赖,还能直接用await()简化代码:
// 先添加依赖:implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.7.3" val location = fusedLocationClient.getCurrentLocation(locationRequest, null).await()
方法二:在持续监听中获取位置后注销回调
如果你已经在用requestLocationUpdates做持续监听,只需在LocationCallback的onLocationResult中拿到有效位置后,调用removeLocationUpdates注销即可:
val locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { super.onLocationResult(locationResult) locationResult.lastLocation?.let { location -> // 处理获取到的位置 Log.d("Location", "获取到位置:${location.latitude}, ${location.longitude}") // 注销回调,停止后续位置更新 fusedLocationClient.removeLocationUpdates(this) } } } // 在LaunchedEffect中启动监听 LaunchedEffect(Unit) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_HIGH_ACCURACY interval = 1000 // 初始监听间隔,拿到位置后就会注销 } fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) } }
注意事项
- 必须先申请并获取
ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限,否则会触发权限异常。 getCurrentLocation可能返回null(比如设备未开定位、无信号),需做好判空处理。
内容的提问来源于stack exchange,提问作者ubndra
相关产品推荐
相关产品推荐

