应用在后台运行一段时间后,Firebase 存储下载任务未完成

Posted

技术标签:

【中文标题】应用在后台运行一段时间后,Firebase 存储下载任务未完成【英文标题】:Firebase Storage download task is not completing after the app has spent some time in the background 【发布时间】:2016-11-04 06:25:19 【问题描述】:

我正在从 Firebase 存储中下载图像,如下所示:

let storage = FIRStorage.storage()
// Create a storage reference from our storage service
let storageRef = storage.reference(forURL: "MY_STORAGE_URL")

let imageRef = storageRef.child("Path_to_image")

// Download image in memory 
let downloadTask = imageRef.data(withMaxSize: 1 * 1024 * 1024) 
    (data, error) -> Void in

    if (error != nil) 

        //Handle the error 

     else 

        guard let imageData = data else 
            print("Unable to unwrap image data.")
            return
        

        let downloadedImage = UIImage(data: imageData)
        //Do some stuff with the image 

    


我还使用以下观察者监视下载发生的情况:

// Observe changes in status
downloadTask.observe(.resume)  (snapshot) -> Void in
    // Download resumed, also fires when the download starts


downloadTask.observe(.pause)  (snapshot) -> Void in
    // Download paused


downloadTask.observe(.progress)  (snapshot) -> Void in
    // Download reported progress


downloadTask.observe(.success)  (snapshot) -> Void in
    // Download completed successfully


downloadTask.observe(.failure)  (snapshot) -> Void in
    //Download failed 

这一切在应用程序首次启动时运行良好。但是,如果应用程序进入后台并且我使用其他一些应用程序(Facebook、Twitter 等),然后将应用程序带回前台,我会遇到问题。如果我让应用程序打开并在前台运行超过或等于 1 小时,我也会遇到问题。

问题是let downloadTask = imageRef.data(withMaxSize: blah blah blah(在上面的第一块代码中)中的完成处理程序永远不会被调用。如果从不调用完成处理程序,我将永远无法解包数据并尝试在我的应用程序中使用图像。

此外,在downloadTask 观察者中,唯一被触发的完成处理程序是.resume.progress.success.failure 事件永远不会被触发。这对我来说似乎是一个 Firebase 存储错误,但我不确定。有没有其他人遇到过类似的问题?我不明白为什么代码在新启动时就可以正常工作,但是在前台一段时间后或在后台一段时间后,图像下载停止工作。提前感谢您提供的任何意见。

【问题讨论】:

我没有看到 enque() 方法被触发。 我的示例几乎直接来自文档。他们不在那里调用enqueue() 方法。你能解释一下为什么这是必要的吗? 如果你想在ios中后台运行,你不需要做一些特殊的事情吗? developer.apple.com/library/content/documentation/iPhone/… 【参考方案1】:

不幸的是,这是目前的预期行为。 Firebase Storage(目前)仅前台:如果应用程序是后台的,我们没有持久化上传URL,并且无法在后台上传,也无法在退出后台后重新启动它,因此它可能被杀死操作系统和项目未上传。

这是我们想要解决的 The Next Big Thing™(our android SDK makes it possible,虽然不容易),但不幸的是,目前我们还没有在这方面取得更多进展。

附带说明一下,活动更改后您的观察者将不存在--downloadTask 一旦应用程序后台运行就消失了,所以当它回到前台时,我们基本上需要一个方法来检索当前后台的所有任务,并允许您备份观察者。比如:

FIRStorage.storage().backgroundedTasks  (tasks) -> Void in
  // tasks is an array of upload and download tasks
  // not sure if it needs to be async

【讨论】:

感谢迈克的回答。为了清楚起见并确保我们相互理解,我并不想在下载大图像的过程中为应用程序设置背景。我只希望这些方法在应用程序处于前台时被调用时能够正常工作。这真的是预期的行为吗?注销并重新登录并不能解决问题。我必须完全重新启动应用程序才能再次开始下载图像。这对我的用户来说非常令人沮丧。有什么解决办法吗? 我一定没有完全理解你的问题,抱歉。更清楚地说,听起来所有的观察者和完成块在前台工作正常,但问题只是在前台很长时间后才开始出现,或者如果应用程序是后台的,然后出现在前台.您是否碰巧有一个示例应用程序并为此进行了复制,以便我们可以在本地对其进行调试?我似乎无法可靠地做到这一点。 不用担心。不幸的是,我没有该应用程序的公共回购。我发现重新创建错误的最简单方法是: 1. 在 Xcode 模拟器中启动应用程序。验证其按预期工作。 2. 等待一小时。一小时内不要触摸应用程序中的任何东西。 3. 尝试下载一些图像。图像不会加载。我知道这很耗时,但这是我发现的唯一可靠的方法来重新创建错误。 @MikeMcDonald 使用 iOS 版 Firebase 存储在后台上传还有什么进展吗?或者至少像 Android 这样的 sessionUri,这样我就可以在 backgroundTask 被杀死后恢复上传。如果不可能,我将不得不使用另一个使用 URLSession 的解决方案,它允许在上传继续时暂停或终止应用程序。

以上是关于应用在后台运行一段时间后,Firebase 存储下载任务未完成的主要内容,如果未能解决你的问题,请参考以下文章

IPhone - 应用程序在后台运行一段时间后表现不同

在我的颤振(android)应用程序中 - Firebase 推送通知在一段时间后停止接收每个用户

后台模式下的多点连接

利用 Firebase 和 Google App Engine 将后台逻辑添加到实时数据

iphone 4S 在后台一段时间后从 XMPP 服务器脱机?

一段时间后如何在iOS中停止后台服务