2018.12.31
https://github.com/Unity-Technologies/BackgroundDownload
BackgroundDownload
针对移动平台后台下载的官方插件, 即使应用程序进入后台或被操作系统退出也会继续执行。可以在下次启动应用程序时选择下载。支持的平台有:Android,iOS和通用Windows平台。 这种下载的好处是什么? 玩家不用在游戏内干等着,可以把应用切到后台等着,干别的事情。
如何使用这些插件
将BackgroundDownload和Plugins文件夹拖放到Unity项目的Assets中。如果您要为Android构建,则必须在“Player Settings”中将“写入权限Write Permission”设置为“External
”。
API
BackgroundDownloadPolicy
Enum允许控制允许下载的网络类型。 iOS不支持。
可能的值:
- UnrestrictedOnly - 使用无限制连接下载,例如Wi-Fi。
- AllowMetered - 允许使用计量连接进行下载,例如移动数据(默认)。
- AlwaysAllow - 允许使用所有网络类型进行下载,包括可能很昂贵的网络类型,例如漫游。
BackgroundDownloadConfig
包含开始后台下载所需的所有数据的结构。此结构必须包含要下载的文件的URL和要存储的文件的路径。如果存在,目标文件将被覆盖。目标路径必须是相对的,结果将放在Application.persistentDataPath中,因为允许应用程序写入的目录不能保证在不同的应用程序运行中相同。 (可选)可以包含要发送的自定义HTTP标头和网络策略。这两个设置无法保证在不同的应用运行中保持不变。
字段:
- System.Uri url - 要下载的文件的URL。
- string filePath - 必须相对的相对文件路径(将在Application.persistentDataPath中)。
- BackgroundDownloadPolicy策略 - 限制下载到某些网络类型的策略。不会跨应用程序运行。
- float progress - 请求进展到多远(0到1),如果未知则为负值。访问此字段可能非常昂贵(特别是在Android上)。
- Dictionary <string,List <string >> requestHeaders - 要发送的自定义HTTP标头。不会跨应用程序运行。
方法:
- void AddRequestHeader(string name,string value) - 将自定义HTTP标头添加到requestHeaders的便捷方法。
BackgroundDownloadStatus
后台下载的状态
Downloading
- 正在进行下载。Done
- 下载已成功完成。Failed
- 下载操作失败。
BackgroundDownload
用于在后台启动和获取下载的类。每个后台下载都可以从协程返回,等待它完成。要释放系统资源,完成后必须通过调用Dispose()或将对象放在using块中来处理每个后台下载。如果在完成之前处理后台下载,它也被取消,在这种情况下结果文件的存在和内容是不确定的。下载完成之前,不得使用目标文件。否则可能会阻止下载写入目标。如果操作系统退出应用程序,则在下次运行时,可以通过访问BackgroundDownload.backgroundDownloads来获取后台下载。 间接的一个好处可以省电,游戏运行是CPU,GPU高消耗的,运行和不运行耗电差别耗时有得
属性:
- static BackgroundDownload [] backgroundDownloads - 包含所有当前下载的数组。
- BackgroundDownloadConfig config - 下载配置。只读。
- BackgroundDownloadStatus status - 下载状态。只读。
- string error - 包含失败下载的错误消息。只读。
方法:
- static BackgroundDownload Start(BackgroundDownloadConfig config) - 使用给定配置开始下载。
- static BackgroundDownload Start(Uri url,String filePath) - 在不需要其他设置时开始下载的便捷方法。
- void Dispose() - 释放资源并删除下载。如果没完成则是取消下载。
例子
在协程中的同一应用程序会话期间下载文件(调用StartCoroutine(StartDownload()))。
IEnumerator StartDownload()
{
using (var download = BackgroundDownload.Start(new Uri("https://mysite.com/file"), "files/file.data"))
{
yield return download;
if (download.status == BackgroundDownloadStatus.Failed)
Debug.Log(download.error);
else
Debug.Log("DONE downloading file");
}
}
从以前的应用程序运行中选择下载并继续下载直到完成
IEnumerator ResumeDownload()
{
if (BackgroundDownload.backgroundDownloads.Length == 0)
yield break;
var download = BackgroundDownload.backgroundDownloads[0];
yield return download;
// deal with results here
// dispose download
download.Dispose();
}
这个插件是下载模块, 所以下载和 对资源的使用是独立的。
从插件中可以看到 Android 平台需要设置的权限等:
BackgroundDownloadConfig config = new BackgroundDownloadConfig
{
filePath = saveFilePath,
url = new Uri(downloadFileURL),
policy = BackgroundDownloadPolicy.UnrestrictedOnly
};
using (var download = BackgroundDownload.Start(config))
{
yield return download;
Debug.Log(download.status);
}
使用BackgroundDownloadConfig,可以AddRequestHeader
首先添加标题信息,并指定可用于下载的网络。
using System;
using System.Collections;
using System.IO;
using Unity.Networking;
using UnityEngine;
using UnityEngine.UI;
public class DownloadAndDisplay : MonoBehaviour
{
[SerializeField]
private string downloadFileURL = "https://user-images.githubusercontent.com/1644563/50053779-1b7a0780-017e-11e9-9736-d88ec4773704.png";
const string saveFilePath = "image.png";
// 由于文件存储目标是相对于Application.persistentDataPath,因此 这个是用于加载,删除等的具体文件路径
string FilePath { get { return Path.Combine(Application.persistentDataPath, saveFilePath); } }
Texture2D texture;
private void Awake()
{
texture = new Texture2D(2, 2);
}
private void OnDestroy()
{
Destroy(texture);
}
public void RemoveFile()
{
if (File.Exists(FilePath))
File.Delete(FilePath);
}
public void DownloadStart()
{
StartCoroutine(DownloadFileTest());
}
IEnumerator DownloadFileTest()
{
BackgroundDownloadConfig config = new BackgroundDownloadConfig
{
filePath = saveFilePath,
url = new Uri(downloadFileURL),
policy = BackgroundDownloadPolicy.Default
};
// 由于Android上的Permission存在错误,因此我想将BackgroundDownload.Start与try-catch结合使用,
// 如果不使用using, 就要手动调用Dispose() 防止泄露
using (var download = BackgroundDownload.Start(config))
{
yield return download;
Debug.Log(download.status);
}
// 在下载完成后立即开始处理并且在最后状态下等待一帧
//如果有后处理(Zip解压等),那么在此时更新屏幕似乎是好的
yield return null;
// 由于下载失败和各种因素导致无法读取,因此请使用try-catch将其括起来
try
{
var data = File.ReadAllBytes(FilePath);
texture.LoadImage(data, false);
GetComponent<RawImage>().texture = texture;
}
catch (IOException e) { Debug.LogError(e); }
}
}