# 版本与插件更新 `@xuqm/rn-update` 提供两类能力: - Android 整包检查、下载、安装和应用商店跳转。 - 可选的 RN 插件检查、安装和启动。 SDK 返回更新信息和当前网络状态,是否弹窗、是否允许使用移动网络以及何时开始下载由宿主 决定。 ## 整包更新 ### 检查 ```ts import { UpdateSDK } from '@xuqm/rn-update' const result = await UpdateSDK.checkAppUpdate() switch (result.status) { case 'UPDATE_AVAILABLE': showUpdateDialog(result.update, result.network) break case 'LOGIN_REQUIRED': case 'SERVICE_DISABLED': case 'NO_UPDATE': // 正常跳过,不阻断应用 break case 'FAILED': // 记录一次非阻断诊断 console.warn(result.errorCode, result.message) break } ``` 检查状态: | 状态 | 宿主建议 | | --- | --- | | `UPDATE_AVAILABLE` | 根据 `forceUpdate` 展示宿主自己的更新弹窗 | | `NO_UPDATE` | 继续启动 | | `LOGIN_REQUIRED` | 未登录时跳过,登录后可再次检查 | | `SERVICE_DISABLED` | 服务未启用,继续运行 | | `FAILED` | 记录诊断,不阻断宿主 | `result.network` 包含连接类型、是否已连接和是否按流量计费。租户平台不替宿主配置网络 策略。 ### 下载并安装 用户确认后调用: ```ts await UpdateSDK.downloadAndInstallApp(result.update!, { destination: 'SDK_PRIVATE', onProgress(progress) { setProgress(progress.percent) }, }) ``` 需要把安装包保留在系统 Downloads: ```ts await UpdateSDK.downloadAndInstallApp(result.update!, { destination: 'PUBLIC_DOWNLOADS', }) ``` 下载失败或应用退出后不会在下次启动时自动继续。 ### 只下载、稍后安装 ```ts import { NativeAppUpdate, UpdateSDK } from '@xuqm/rn-update' const downloaded = await UpdateSDK.downloadApk(result.update!, { destination: 'SDK_PRIVATE', }) console.log(downloaded.localPath) await NativeAppUpdate.installDownloaded({ versionCode: result.update!.versionCode!, sha256: result.update!.sha256, }) ``` 取消当前下载: ```ts await NativeAppUpdate.cancel() ``` 如果系统禁止安装未知来源应用: ```ts await NativeAppUpdate.openInstallPermissionSettings() ``` ### 跳转应用商店 宿主不传商店地址,只传检查接口返回的更新对象: ```ts const opened = await UpdateSDK.openStore(result.update!) ``` Android 会优先打开当前设备对应的应用商店,不可用时使用平台提供的通用下载页。iOS 或 HarmonyOS 没有配置商店地址时返回 `false`,宿主应提示当前无法提供下载服务。 ### 忽略可选版本 ```ts await UpdateSDK.ignoreAppVersion(result.update!.versionCode!) const ignoredVersion = await UpdateSDK.getIgnoredAppVersion() await UpdateSDK.clearIgnoredAppVersion() ``` 强制更新不能被忽略。 ## 不启用插件化 普通项目可以只使用上述整包更新 API,不创建 `common/app/buz` 模块,也不需要接入插件 运行时。后续需要插件化时再执行初始化命令即可。 ## 启用插件化 在项目根目录执行交互式初始化: ```bash pnpm exec xuqm-rn init pnpm run xuqm:doctor ``` 初始化工具会创建 `xuqm.modules.json`、补充必要脚本并提示宿主完成最少原生配置。不要 手工复制其他项目的模块表。 Metro 使用: ```js const { getDefaultConfig } = require('@react-native/metro-config') const { withXuqmModuleConfig } = require('@xuqm/rn-update/metro') module.exports = withXuqmModuleConfig(getDefaultConfig(__dirname)) ``` Android 宿主应用一次构建脚本: ```groovy apply from: file("../../node_modules/@xuqm/rn-update/android/xuqm-bundles.gradle") ``` ### 注册宿主运行时 ```ts import { XuqmRuntime } from '@xuqm/rn-update' XuqmRuntime.configure({ plugins: pluginRegistrations, context: { navigate(route, params) { navigationRef.navigate(route, params) }, emit(event, payload) { hostEvents.emit(event, payload) }, getHostState() { return appStore.getState() }, }, async loadBundle(_moduleId, bundlePath) { await bundleLoader.load(bundlePath) }, }) ``` 模块入口注册: ```ts import { definePlugin } from '@xuqm/rn-update' definePlugin({ moduleId: 'orders', activate(context) { context.navigate('OrdersHome') }, }) ``` ### 检查与安装插件 自动完成检查和安装: ```ts const plan = await UpdateSDK.checkAndInstallPlugin('orders', { onProgress(moduleId, progress) { console.log(moduleId, progress.percent) }, }) await XuqmRuntime.activate('orders', { reloadBundle: plan !== null, }) ``` 宿主需要先展示确认弹窗时: ```ts const plan = await UpdateSDK.checkPluginRelease('orders') if (plan && (await showPluginUpdateDialog(plan))) { await UpdateSDK.installPluginRelease(plan) } ``` 只检查不会下载或修改本地状态。插件检查失败时,宿主应继续打开已有的本地健康版本。 ## 启动策略 - 启动时先检查整包更新。 - 不需要整包更新时,再检查 App 插件。 - 业务插件在进入前分别检查。 - Debug 默认不自动检查;开发页可以显式使用 `UpdateSDK.developer` 下的测试入口。 - 更新 SDK 不绘制业务弹窗,所有提示和确认交互由宿主实现。 ## 打包与发布 初始化生成的脚本支持 Debug、Release、插件构建和上传。发布令牌只通过 CI 环境变量 `XUQM_API_TOKEN` 注入,不写入项目配置、源码或产物。 SDK 自身制品发布与应用/插件发布是不同操作。应用开发者不需要发布 SDK,也不得把 SDK 发布凭据加入宿主工程。