微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

FusedLocationProvider 在 Worker / CoroutineWorker 中不起作用

如何解决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 重复调用 Fragment 每次都有效。

  • 如果我启动应用程序并立即触发工作程序,它在第一次调用时按预期工作,但在后续调用中失败。

  • 当应用被终止时,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 举报,一经查实,本站将立刻删除。