如何解决FusedLocationProvider 在 Worker / CoroutineWorker 中不起作用
在我的 LocationResultRepositoryImpl
类中,我有这个 callbackFlow
:
override suspend fun getLastKNownLocation(context: Context): Flow<Result<Location>> =
callbackFlow {
Timber.tag(TAG).d("Getting last kNown location...")
val subscription = FusedLocationProviderClient(context).lastLocation
.addOnCompleteListener {
var result: Result<Location> = if (it.isSuccessful) {
when {
it.result != null -> Result.success(it.result)
else -> Result.failure(Error("empty result"))
}
} else {
Result.failure(Error("empty result"))
}
try {
offer(result)
} catch (e: Throwable) {
// Event Could not be sent to the flow
Timber.tag(TAG).d("Error = $e")
}
}
awaitClose { subscription.isComplete }
}
我的CoroutineWorker
类如下:
@HiltWorker
class BackgroundFetchWorker @AssistedInject constructor(
@Assisted context: Context,@Assisted params: WorkerParameters,private val locationResultRepository: LocationResultRepository,@Iodispatcher private val iodispatcher: Coroutinedispatcher
) : CoroutineWorker(context,params) {
override suspend fun doWork(): Result = withContext(iodispatcher) {
return@withContext try {
locationResultRepository.getLastKNownLocation(applicationContext).collect {
when {
it.isSuccess -> println("loc = ${it.getorNull()?.latitude}")
else -> throw Exception("Could not get location")
}
}
workManager.enqueueUniqueWork(
applicationContext.resources.getString(R.string.app_widget_update_worker_tag),ExistingWorkPolicy.REPLACE,oneTimeBackgroundFetchWorkRequest
)
Result.success()
} catch (e: Exception) {
println("Error: $e")
Result.failure()
}
}
}
-
当应用被终止时,
callbackFlow
总是失败。
我确定我在这里忽略了一些简单的东西,但我已经被卡住了一段时间。感谢任何帮助,谢谢!
编辑:使用下面的函数而不是 callbackFlow
观察到的相同行为。尽管这会在 .addOnSuccessListener
中返回,但该位置为空。知道为什么我会在 Fragment
类中获得更新而不是在 CoroutineWorker
中获得更新吗?
suspend fun FusedLocationProviderClient.awaitLastLocation(): Location =
suspendCancellableCoroutine { continuation ->
lastLocation
.addOnSuccessListener { location ->
if (location != null)
continuation.resume(location,null)
else
continuation.resumeWithException(Exception("location is null"))
}
.addOnFailureListener { e ->
// Resume the coroutine by throwing an exception
continuation.resumeWithException(e)
}
}
编辑 2:我在常规 Worker
中测试了更“传统” 回调的实现,并观察到了类似的行为。请参见下面的示例:
@HiltWorker
class MyWorker @AssistedInject constructor(
@Assisted context: Context,private val cancelTokenSource: CancellationTokenSource
) : Worker(context,params) {
private var location: Location? = null
private var fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
private var locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
}
}
override fun doWork(): Result {
return try {
(fusedLocationClient as FusedLocationProviderClient)
.lastLocation
.addOnCompleteListener { task ->
when {
task.isSuccessful && task.result != null -> {
location = task.result
Timber.tag(TAG).d("Location : $location")
(fusedLocationClient as FusedLocationProviderClient).removeLocationUpdates(locationCallback)
return@addOnCompleteListener
}
else -> throw Exception("Failed to get location.")
}
}
Result.success()
} catch (e: Exception) {
Timber.tag(TAG).e("Error: $e")
Result.failure()
}
}
也许系统限制了对 lastLocation
的调用?我认为只有当应用程序在后台时才请求位置更新受到限制。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。