下载更新
了解下载和启动更新的策略。
本页面中的以下所有信息仅适用于 启用EX_UPDATES_NATIVE_DEBUG
后 的发布版本和调试版本。
在本节中,我们将介绍下载和启动更新的不同策略。目标是确保终端用户在应用发布后尽快采用最新版本,而不会因引入缓慢的加载屏幕或其他问题而牺牲用户体验。这些策略并不互相排斥,你可以根据应用的需求进行混合搭配。
¥In this section, we'll cover the different strategies for downloading and launching updates. The goal is to ensure that the end user adopts the latest version of the app as soon as possible after it is published, without sacrificing the user experience by introducing slow loading screens or other issues. The strategies are not mutually exclusive, and you can mix and match them as needed for the requirements of your app.
默认情况下,更新在启动时异步加载
¥Updates are loaded asynchronously on startup by default
默认行为是在应用冷启动(从终止状态启动)时检查更新,并在更新可用时下载。此过程不会阻止应用的加载,因此使用此策略时,终端用户仅在更新发布后冷启动应用时加载更新,然后在某个时间点终止并重新启动应用(例如,从操作系统的最近应用列表中关闭应用,或者关闭设备然后再打开)。
¥The default behavior is to check for an update when the app is cold booted (launched from a killed state) and download the update if it's available. This process does not block loading the app, so when using this strategy the end user will only load the update when they cold boot the app after an update has been published, and then at some point kill and restart the app (for example, if they close it from the recent apps list on the OS or if they turn the device off and on).
这种行为是安全的,因为它不会干扰应用启动以等待网络请求完成(在常见的实际情况下,当用户发现自己的网络连接速度很慢并且卡在加载屏幕上几秒钟时,这将是糟糕的用户体验)。缺点是用户需要更长的时间来适应最新版本的应用。如果理想的情况是更新发布后立即被所有用户采用,那么此策略远远达不到此要求。
¥This behavior is safe because it doesn't interfere with app startup to wait for a network request to complete (which would be a bad user experience in common real-world cases where a user finds themself with a slow connection and they are stuck on a loading screen for several seconds). The downside is that it takes much longer for users to adopt the latest version of the app. If the ideal is for an update to be adopted immediately by all users as soon as it is published, then this strategy falls very short of that.
What if I want to always block app startup until the latest update is downloaded?
We recommend against this strategy because the resulting user experience is extremely poor. Typically when a user is stuck waiting on a splash screen when booting an app, they will close the app and try again (and so downloading the update won't complete), or give up and use another app. When the users' device is connected to a slow network, even when there is no update, they may have to wait several seconds or more to load the app. If ensuring that your users always have the latest version of your app is critical, you may want to explore one of the other strategies explained here.
How can I disable the default behavior?
You can disable the default behavior by setting the checkAutomatically
option to NEVER
in the updates
configuration. This will prevent the app from checking for updates and downloading them automatically.
Checking for updates while the app is running
You can use Updates.checkForUpdateAsync()
to check for updates while the app is running. This will return a promise that resolves to a UpdateCheckResult
object, with isAvailable
set to true
if an update is available, and information about the update in the manifest
property.
If an update is available, you can use the Updates.downloadAsync()
method to download the update. This will return a promise that resolves when the download is complete. Finally, you can use the Updates.reloadAsync()
method to reload the app with the new version. The useUpdates()
hook can also be used to monitor the state of the expo-updates
library from a React component.
What are common patterns for checking for updates while the app is running?
- You can check for updates at various points in your app's lifecycle, such as when it is foregrounded or at some interval. When an update is found, you may want to show a dialog to the user to prompt the user to update.
- You can check for updates at launch and display your own custom loading screen, if it is very important for your use case to ensure that users always get the latest version at launch.
Checking for updates while the app is backgrounded
You can use expo-background-task
to check for updates while the app is backgrounded. To do this, use the same Updates.checkForUpdateAsync()
and Updates.downloadAsync()
methods as you would in the foreground, but execute them inside of a background task. This is a great way to ensure that the user always has the latest version of the app, even if they have not opened the app in a while.
It's worth considering whether you want to reload the app after an update is downloaded in the background, or wait for the user to close and reopen it. If you choose to only download it in the background and not apply it, this should still be useful to ensure that the next boot will immediately have the latest version, and it will lead to a faster adoption rate for updates compared to the default behavior.
An example of how to check for updates in the background
To ensure the background task is registered when the application starts, import and invoke the setupBackgroundUpdates
function within the top-level component.
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();
Should I also apply the update with Updates.reloadAsync() when the app is backgrounded?
Support for calling Updates.reloadAsync()
while the app is backgrounded is experimental. This is a new feature and it is not widely used, be sure to monitor for crashes when you first enable it. Downloading an update in the background is safe.
Reloading an update while the app is backgrounded can be a great way to ensure that the user has the latest version of the app when they open it again. However, it is important to note that, unless you persist the state that the app was in at the time it was backgrounded and restore that state, the user will experience a cold boot when they open the app again. One way to mitigate this is to only do a reload in the background if the app has been inactive for a certain period of time, after which a user is unlikely to expect the app to restore its previous state.
关键/强制更新
¥Critical/mandatory updates
expo-updates
库不提供对关键/强制更新的一级支持。但是,你可以实现自己的逻辑来检查关键更新并手动应用它们。expo/UpdatesAPIDemo
代码库 包含一个解决此问题的示例。你可以将该方法与上述策略结合使用来检查更新。
¥There is no first-class support for critical/mandatory updates in the expo-updates
library. However, you can implement your own logic to check for critical updates and apply them manually. The expo/UpdatesAPIDemo
repository contains an example of one way to approach this. You can combine that approach with the strategies above to check for updates.
控制从客户端加载哪些更新
¥Controlling which update to load from the client side
使用 EAS 更新的典型方法是将单个更新 URL 和一组请求标头(例如更新渠道名称)嵌入到应用的构建中。要控制加载哪些更新,你可以通过 eas update
命令或 EAS 仪表板在服务器上进行更改。例如,你将新更新发布到构建指向的通道,然后构建将在下次启动时获取该更新。使用此方法不会下载发布到与你的构建指向不同的通道的更新。
¥The typical way to use EAS Update is to have a single update URL and a set of request headers (such as update channel name) embedded in a build of your app. To control which update is loaded, you make changes on the server through the eas update
command or the EAS dashboard. For example, you publish a new update to a channel that your build is pointing to, then the build fetches that update on the next launch. Updates published to a channel different from the one your build is pointing to will not be downloaded with this approach.
你可以使用 Updates.setUpdateURLAndRequestHeadersOverride()
方法在运行时覆盖更新 URL 和请求标头。如果你想在应用运行时加载特定更新或更改更新渠道,这将非常有用。了解更多。
¥You can override the update URL and request headers at runtime using the Updates.setUpdateURLAndRequestHeadersOverride()
method. This can be useful if you want to load a specific update or change the update channel while the app is running. Learn more.
监控更新的采用情况
¥Monitoring adoption of updates
更新详情页面(例如:https://expo.dev/accounts/[account]/projects/[project]/updates/[id]
)显示已运行更新的用户数量指标,以及安装失败数量(下载并尝试运行更新但崩溃的用户)。
¥The details page for an update (for example: https://expo.dev/accounts/[account]/projects/[project]/updates/[id]
) shows metrics for the number of users who have run the update, in addition to the number of failed installs (users who download and attempted to run the update, but it crashed).
部署页面(例如:https://expo.dev/accounts/[account]/projects/[project]/deployments/production/[runtime-version]
)包含一个表格和图表,显示在给定时间段内运行过与特定更新渠道和运行时版本组合相关的每个更新的用户数量。
¥The deployments page (for example: https://expo.dev/accounts/[account]/projects/[project]/deployments/production/[runtime-version]
) includes a table and chart that shows the number of users who have run each update related to a particular update channel and runtime version combination, over a given time period.