我想使用LocationManager.requestSingleUpdate()
获取设备的当前全球定位系统位置。下面的代码用于在kotlin挂起函数中包装对LocationManager的调用:
private var locationManager =
context.getSystemService(LOCATION_SERVICE) as LocationManager
@RequiresPermission("android.permission.ACCESS_FINE_LOCATION")
suspend fun getCurrentLocationPreS(): Coordinate? = suspendCoroutine {
val handlerThread = HandlerThread("getCurrentLocation() HandlerThread")
handlerThread.start()
try {
// Use of deprecated function is ok because we are pre android S
locationManager.requestSingleUpdate(
LocationManager.GPS_PROVIDER,
{ location ->
handlerThread.quit()
it.resume(
Coordinate(
location.latitude,
location.longitude
)
)
},
handlerThread.looper
)
}
catch (ex: Exception) {
ex.printStackTrace()
it.resumeWithException(ex)
}
}
如您所见,我使用suspendCoroutine
进行异步位置调用。这个实现对某些设备有效,但我在其他设备上有问题。有时,由于位置更新回调没有被调用,因此支持函数永远不会返回和等待。该应用程序还具有所需的权限,并且启用了GPS。
什么边情况会导致函数永远不会返回的状态?
Logcat不表示任何异常或其他错误。该应用程序也不会崩溃。唯一的症状是getCurrentLocationPreS()
永远不会回来。
发布于 2022-04-01 16:42:26
仅仅因为GPS已启用并不意味着它正在正常工作。当你在室内或高楼大厦密集的地区时,信号可能很差。如果您查看requestSingleUpdate
的实现,您将看到它使用的超时时间为30,因此,如果超时过期,您的回调将永远不会执行,您的协同线将无限期地被卡住。
我建议要么为这个调用使用超时,要么考虑使用FusedLocationProviderClient
,这样您就可以以更安全的方式获得最后一个已知的位置。
我还建议使用Looper.getMainLooper()
,与确保正确管理HandlerThread
相比,临时切换到主线程的运行时开销可以忽略不计。
所以我对这个的看法是这样的:
suspend fun getCurrentLocationPreS(): Coordinate? = withTimeoutOrNull(30.seconds){
suspendCoroutine { cont ->
try {
// Use of deprecated function is ok because we are pre android S
locationManager.requestSingleUpdate(
LocationManager.GPS_PROVIDER,
{ location ->
cont.resume(
Coordinate(
location.latitude,
location.longitude
)
)
},
Looper.getMainLooper()
)
}
catch (ex: Exception) {
ex.printStackTrace()
cont.resumeWithException(ex)
}
}
}
https://stackoverflow.com/questions/71683149
复制相似问题