下载更新
编辑页面
了解下载和启动更新的策略。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
本页中的所有以下信息仅适用于发布构建,以及启用了 `EX_UPDATES_NATIVE_DEBUG` 的调试构建。
在本节中,我们将介绍下载和启动更新的不同策略。目标是在不牺牲用户体验、避免引入缓慢的加载界面或其他问题的前提下,确保最终用户在更新发布后尽快采用应用的最新版本。这些策略并不互斥,你可以根据应用的需求按需组合使用。
默认情况下,更新会在启动时异步加载
默认行为是在应用冷启动时(从被终止的状态启动)检查更新,并在有可用更新时下载它。这个过程不会阻塞应用加载,因此使用这种策略时,最终用户只有在更新发布后冷启动应用时才会加载更新,然后在某个时候终止并重启应用(例如,他们从操作系统的最近使用应用列表中关闭它,或者关闭并重新打开设备)。
这种行为是安全的,因为它不会为了等待网络请求完成而干扰应用启动(在常见的真实场景中,如果用户遇到慢速连接并被困在加载屏幕上数秒,这会带来很差的用户体验)。缺点是用户采用应用最新版本所需的时间会长得多。如果理想目标是让所有用户在更新一发布后就立即采用,那么这种策略与目标相差甚远。
如果我想始终阻塞应用启动,直到最新更新下载完成,该怎么办?
我们不建议采用这种策略,因为由此带来的用户体验极差。通常,当用户在启动应用时被困在启动画面上等待,他们会关闭应用并再次尝试(因此更新下载不会完成),或者直接放弃并使用其他应用。如果用户的设备连接的是慢速网络,即使没有更新,他们也可能需要等待数秒甚至更久才能加载应用。如果确保用户始终拥有你应用的最新版本至关重要,你可能需要考虑这里介绍的其他策略之一。
如何禁用默认行为?
你可以在 updates 配置中将 checkAutomatically 选项设置为 NEVER,从而禁用默认行为。这样应用就不会自动检查更新并下载它们。
在应用运行时检查更新
你可以使用 Updates.checkForUpdateAsync() 在应用运行时检查更新。这将返回一个 promise,解析为一个 UpdateCheckResult 对象,如果有可用更新,则其 isAvailable 会被设为 true,并且更新信息会出现在 manifest 属性中。
如果有可用更新,你可以使用 Updates.fetchUpdateAsync() 方法下载更新。这将返回一个 promise,并在下载完成时解析。最后,你可以使用 Updates.reloadAsync() 方法用新版本重新加载应用。useUpdates() hook 也可用于在 React 组件中监视 expo-updates 库的状态。
检查应用运行时更新的常见模式有哪些?
- 你可以在应用生命周期中的不同时间点检查更新,例如在 应用进入前台时 或按固定时间间隔检查。当发现更新时,你可能希望向用户显示一个对话框,提示用户更新。
- 如果你的用例非常重要,必须确保用户在启动时总能获得最新版本,那么你可以在启动时检查更新并显示你自己的自定义加载界面。
在应用处于后台时检查更新
你可以使用 expo-background-task 在应用处于后台时检查更新。为此,请像在前台一样使用相同的 Updates.checkForUpdateAsync() 和 Updates.fetchUpdateAsync() 方法,但要在后台任务中执行它们。这是确保用户始终拥有应用最新版本的绝佳方式,即使他们已经有一段时间没有打开应用了。
值得考虑的是,你是希望在后台下载更新后立即重新加载应用,还是等用户关闭并重新打开它。如果你选择仅在后台下载而不应用更新,这仍然有助于确保下一次启动时立即使用最新版本,并且与默认行为相比,这会带来更快的更新采用率。
在后台检查更新的示例
为确保应用启动时注册后台任务,请在顶层组件中导入并调用 setupBackgroundUpdates 函数。
import * as TaskManager from 'expo-task-manager'; import * as BackgroundTask from 'expo-background-task'; import * as Updates from 'expo-updates'; const BACKGROUND_TASK_NAME = 'task-run-expo-update'; export const setupBackgroundUpdates = async () => { TaskManager.defineTask(BACKGROUND_TASK_NAME, async () => { const update = await Updates.checkForUpdateAsync(); if (update.isAvailable) { await Updates.fetchUpdateAsync(); await Updates.reloadAsync(); } return Promise.resolve(); }); await BackgroundTask.registerTaskAsync(BACKGROUND_TASK_NAME, { minimumInterval: 60 * 24, }); }; setupBackgroundUpdates();
当应用处于后台时,我也应该使用 Updates.reloadAsync() 应用更新吗?
在应用处于后台时调用 Updates.reloadAsync() 的支持是实验性的。这是一个新功能,且尚未被广泛使用,首次启用时务必监控是否发生崩溃。在后台下载更新是安全的。
当应用处于后台时重新加载更新,可以很好地确保用户下次打开应用时使用的就是最新版本。不过需要注意的是,除非你持久化应用处于后台时的状态并在之后恢复该状态,否则用户下次打开应用时会经历一次冷启动。缓解这一问题的一种方法是:只有当应用已经处于非活跃状态达到某个时间段后,才在后台执行重新加载;在这之后,用户通常不会期望应用恢复到之前的状态。
关键/强制更新
expo-updates 库并不原生支持关键/强制更新。不过,你可以实现自己的逻辑来检查关键更新并手动应用它们。expo/UpdatesAPIDemo 仓库 包含了一个实现思路示例。你可以将该方法与上面的策略结合起来检查更新。
从客户端控制要加载哪个更新
使用 EAS Update 的典型方式,是在你应用的构建中嵌入单一的更新 URL 和一组请求头(例如更新通道名称)。要控制加载哪个更新,你需要通过 eas update 命令或 EAS 控制台在服务器端进行更改。例如,你向构建所指向的通道发布一个新更新,然后该构建会在下一次启动时获取该更新。按照这种方式,发布到与构建所指向的不同通道的更新将不会被下载。
你可以在运行时使用 Updates.setUpdateURLAndRequestHeadersOverride() 方法覆盖更新 URL 和请求头。如果你希望在应用运行时加载特定更新或更改更新通道,这会很有用。了解更多。
监控更新的采用情况
更新的详情页面(例如:https://expo.dev/accounts/[account]/projects/[project]/updates/[id])会显示运行该更新的用户数量,以及安装失败的数量(即已下载并尝试运行该更新,但应用崩溃的用户)。
部署页面(例如:https://expo.dev/accounts/[account]/projects/[project]/deployments/production/[runtime-version])包含一个表格和图表,显示在给定时间段内,针对某个特定更新通道与运行时版本组合,每个相关更新被运行的用户数量。