在 iOS 上,当应用程序进入后台时 UnityWebRequest 下载停止

Posted

技术标签:

【中文标题】在 iOS 上,当应用程序进入后台时 UnityWebRequest 下载停止【英文标题】:On iOS, UnityWebRequest download stops when app goes to background 【发布时间】:2020-06-21 03:33:08 【问题描述】:

我使用 UnityWebRequestAssetBundle.GetAssetBundle 下载位于远程服务器上的资产包。虽然在 android 上一切正常,但在最小化应用程序(或设备进入睡眠状态)时,ios 上的下载会停止。

当我再次将应用程序置于前台时,XCode 显示以下日志:

-> applicationWillResignActive()
-> applicationDidEnterBackground()
2020-03-08 08:37:51.571235+0100 app[3852:2943256] Can't end BackgroundTask: no background task exists with identifier 1 (0x1), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
-> applicationWillEnterForeground()
2020-03-08 08:37:55.169337+0100 app[3852:2943564] [] nw_read_request_report [C4] Receive failed with error "Software caused connection abort"
2020-03-08 08:37:55.194339+0100 app[3852:2943564] Task <015CA857-5213-4905-8F1B-4A0E3DA330DE>.<5> HTTP load failed, 350/5095859 bytes (error code: -1005 [1:53])
2020-03-08 08:37:55.195303+0100 app[3852:2943564] Task <446A65DA-5ACF-493C-AE8F-B746364F4A9E>.<6> HTTP load failed, 693/0 bytes (error code: -1005 [1:53])
2020-03-08 08:37:55.197007+0100 app[3852:2943431] Task <015CA857-5213-4905-8F1B-4A0E3DA330DE>.<5> finished with error [-1005] Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo=_kCFStreamErrorCodeKey=53, NSUnderlyingError=0x2800ced00 Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo=NSErrorPeerAddressKey=<CFData 0x282ca0be0 [0x1e218bcf0]>length = 16, capacity = 16, bytes = 0x10021f40c0a801300000000000000000, _kCFStreamErrorCodeKey=53, _kCFStreamErrorDomainKey=1, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <015CA857-5213-4905-8F1B-4A0E3DA330DE>.<5>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <015CA857-5213-4905-8F1B-4A0E3DA330DE>.<5>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=http://192.168.1.48:8000/Mobile/dlc1, NSErrorFailingURLKey=http://192.168.1.48:8000/Mobile/dlc1, _kCFStreamErrorDomainKey=1

C#代码:

public static AssetBundleDownloadProgress DownloadBundle (string bundleName, bool forImmediateLoad, DownloadBundleFinishedDelegate finished, DownloadBundleErrorDelegate error)
 
     UnityWebRequest wr;

     if (HashDictionaryRemote.ContainsKey(bundleName))
     
         uint crc = CRCDictionaryRemote[bundleName];
         Hash128 hash = HashDictionaryRemote[bundleName];

         wr = UnityWebRequestAssetBundle.GetAssetBundle (SERVER_URL + bundleName, hash, crc);
     
     else
     
         wr = UnityWebRequestAssetBundle.GetAssetBundle (SERVER_URL + bundleName);
     

     wr.disposeDownloadHandlerOnDispose = true;
     wr.SetRequestHeader ("Cache-Control", "no-cache, no-store, must-revalidate");
     wr.SetRequestHeader ("Pragma", "no-cache");
     wr.SetRequestHeader ("Expires", "0");

     AssetBundleDownloadProgress progress = new AssetBundleDownloadProgress(wr);

     Instance.StartCoroutine(DownloadBundleCoroutine (wr, forImmediateLoad, progress, bundleName, finished, error));

     return progress;
 

 private static IEnumerator DownloadBundleCoroutine (UnityWebRequest wr, bool forImmediateLoad, AssetBundleDownloadProgress progress, string bundleName, DownloadBundleFinishedDelegate finished, DownloadBundleErrorDelegate error)
 
     yield return wr.SendWebRequest();

     if (wr.isNetworkError) 
     
         error (wr.error);
      
     else
     
         AssetBundle bundle = ((DownloadHandlerAssetBundle)wr.downloadHandler).assetBundle;

         if (bundle == null) 
         
             error.Invoke($"Error loading bundle bundleName, probably another bundle with same files is already loaded.");
          
         else
         
             finished.Invoke(bundle, progress);

             if(!forImmediateLoad)
                 bundle.Unload(true);
         
     
 

我使用 Unity 2019.2

任何帮助将不胜感激!

【问题讨论】:

一般情况下,IOS会在后台停止应用,所以你应该让应用在后台运行。 bitbucket.org/Unity-Technologies/iosnativecodesamples/src/… 有帮助 @BrianChoi 我很确定我已经看到其他 iOS 应用程序在后台下载东西。你确定吗? 据我了解,您提供的链接是关于后台提取的,这与我尝试做的不同。 【参考方案1】:

如 cmets 中所述,无法使用常规代码在 iOS 上的后台下载内容。 UnityWebRequest 支持NSURLSession’s dataTaskWithRequest。这些不能在后台运行。可以使用的是NSURLSessionTask 的某些变体。正如 Brian Choi 在 cmets 中提到的那样,在后台下载资产的应用程序使用后台获取来执行此操作,它使用这些 NSURLSessionTasks。它们直接写入磁盘,在这种情况下,下载将交给操作系统完成。

可以在您的应用处于前台时主动监控下载,并将继续在后台运行,尽管其优先级将由操作系统根据网络、电池、热量和其他运行应用的情况进行管理设备。

Unity 为此目的提供了一个后台下载程序包。

https://github.com/Unity-Technologies/BackgroundDownload

为了使用它加载资产包,您必须下载到应用程序的 persistentDataPath,然后使用 AssetBundle.LoadFromFile() 来实际加载资产包。

【讨论】:

非常感谢您的回复。真的很有趣的东西。我不知道那个包。

以上是关于在 iOS 上,当应用程序进入后台时 UnityWebRequest 下载停止的主要内容,如果未能解决你的问题,请参考以下文章

UIWebView:当应用程序进入后台时,iOS 6 中的 HTML5 音频暂停

当应用程序进入和退出后台时更新ios中的计时器

当 iOS 应用程序进入后台时,是不是会暂停冗长的任务?

当应用程序进入后台时,在前台执行的长时间运行的任务被挂起

当 iOS 应用程序确实进入后台时,TCP 和 UDP(使用多播)连接会发生啥情况

AVAudioPlayer 后台任务无法在 iOS 5.0.1 设备上运行,但在 iOS 5 模拟器上运行