SDK API 参考
查阅公开入口、配置默认值、Hooks、检查结果与错误模型。
更新于 2026-09-14
本页内容
- 概览
- 客户端类
- ClientOptions
- React 接入
- CheckResult 与版本信息
- 元数据与崩溃报告关联
- 错误与事件
- checkUpdate(params?)
- downloadUpdate(info?)
- downloadAndInstallApk(url)
- 1. 添加安装权限
- 2. 添加升级按钮
- 3. 处理系统授权和安装结果
- markSuccess()
- currentVersionInfo
- getCurrentVersionInfo()
- restartApp()
- resetToPackagedBundle(options?)
- switchVersion(info?)
- switchVersionLater(info?)
- parseTestQrCode(code)
- useUpdateProgress()
- dismissError()
- 自定义更新界面
- 检查、下载和重载钩子
- 原生启动检查
- captureException(error, context?)
- Android 混编:setCustomInstanceManager
先完成最小接入。本页用于查找参数,不要求一次配置所有选项。示例默认已有一个客户端实例;不要为错误上报或动态配置再创建第二个实例。
概览
Pakta SDK(npm 包 rn-update)的公开 API 全部从包入口导出。核心分五块:
Pakta客户端类与ClientOptions配置UpdateProvider(别名PaktaProvider)React 接入层useUpdate()/useUpdateProgress()/usePakta()Hooks更新元数据与崩溃报告关联
UpdateError错误类型与事件模型
客户端类
import { Pakta } from 'rn-update';
const client = new Pakta({
appKey: '<你的 appKey>',
updateStrategy: 'silentAndLater',
});
// 运行中动态更新配置(合并新配置,并通知 Provider)
client.setOptions({ checkStrategy: 'onAppResume' });
// 手动上报 JS 异常(默认自动监听未捕获的 JS 错误)
client.captureException(error, { context: 'checkout' });ClientOptions
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
appKey | string | 必填 | 控制台分配的平台 appKey |
server | { main: string[]; queryUrls?: string[] } | 官方默认端点 | 自托管服务地址与端点发现清单 |
updateStrategy | 见下表 | 生产为 'alertUpdateAndIgnoreError',开发为 'alwaysAlert' | 更新提示与生效策略 |
checkStrategy | 'onAppStart' | 'onAppResume' | 'both' | null | 'both' | 检查时机;null 关闭 JS 自动检查 |
autoMarkSuccess | boolean | true | 自动确认当前版本健康 |
autoMarkSuccessDelayMs | number | 1000 | 自动确认延迟;关键模块加载晚时调大 |
healthCheck | () => boolean | Promise<boolean> | — | 确认前的健康检查;返回 false 跳过本次确认 |
maxRetries | number | 3 | 下载失败重试次数 |
logger | ({ type, data }) => void | — | 更新事件记录器 |
locale | 'zh' | 'en' | 'zh' | 内置提示文案语言 |
debug | boolean | false | 允许在开发构建检查和下载;实际生效仍用 Release |
throwError | boolean | false | 把更新错误抛给 JS 层 |
testChannel | boolean | true | 是否响应测试二维码/深链;生产建议 false |
beforeCheckUpdate / afterCheckUpdate | 钩子 | — | 检查前后拦截与回调 |
beforeDownloadUpdate / afterDownloadUpdate | 钩子 | — | 下载前后拦截与回调 |
beforeReload | (ctx: { type: 'switchVersion' | 'restartApp' }) => … | — | 重载前拦截 |
onPackageExpired | 钩子 | — | 原生包过期时拦截默认行为 |
disableTelemetry | boolean | false | 关闭客户端遥测及 JS 错误传输 |
disableErrorReporting | boolean | false | 单独关闭 JS 错误上报 |
disableNativeCheck | boolean | false | 关闭原生冷启动检查,见下方说明 |
dismissErrorAfter | number | 不自动清除 | 自动清除 lastError 的延迟,毫秒 |
overridePackageVersion | string | 原生实际版本 | 诊断时覆盖 JS 请求版本,不会修改安装包;正常发布不设置 |
updateStrategy 取值:'silentAndNow'、'silentAndLater'、'alertUpdateAndIgnoreError'、'alwaysAlert'、null。当前 Provider 在手动检查/下载后仍可能弹窗;完全自定义流程使用下方实例 API 示例。
React 接入
import { Pakta, UpdateProvider, PaktaProvider, useUpdate, usePakta, useUpdateProgress } from 'rn-update';UpdateProvider/PaktaProvider(别名)——接收clientprop;同一进程重复挂载第二个 Provider 会直接抛错。useUpdate()—— 读取更新状态与动作(见下)。useUpdateProgress()—— 单独订阅下载进度{ hash, received, total, progress? }。usePakta()——useUpdate()的别名,返回相同状态与动作;实例通过useUpdate().client取得。
useUpdate() 返回的 UpdateContextValue:
| 成员 | 说明 |
|---|---|
updateInfo | 最近一次 CheckResult |
lastError | 最近一次错误 |
currentHash / packageVersion | 当前热更新 hash 与原生包版本 |
currentVersionInfo | { name?, description?, metaInfo? } |
checkUpdate(params?) | 手动检查 |
downloadUpdate(info?) | 下载 |
switchVersion(info?) | 立即切换已下载版本(重载 JS) |
switchVersionLater(info?) | 下次启动生效 |
markSuccess() | 确认当前版本健康 |
restartApp() | 重启应用 |
resetToPackagedBundle(options?) | 回到内置 bundle |
downloadAndInstallApk(url) | 下载并安装原生升级包(原生包过期场景) |
parseTestQrCode(code) | 解析测试二维码/深链 |
dismissError() | 清除 lastError |
CheckResult 与版本信息
interface CheckResult {
upToDate?: boolean; // 已是最新
update?: boolean; // 有可用更新
expired?: boolean; // 原生包过期,downloadUrl 指向新安装包
paused?: 'app' | 'package'; // 应用或原生包暂停
downloadUrl?: string; // 过期安装包地址
bundleStatus?: 'matched' | 'rebuiltSameJs' | 'unknownBundle';
name?: string; // 版本名
hash?: string; // 版本 hash
description?: string; // 版本描述
metaInfo?: string; // 自定义元信息(JSON 字符串)
config?: { rollout?: Record<string, number>; forceBoot?: boolean };
pdiff?: string; // 精确差分包地址
diff?: string; // 普通差分包地址
full?: string; // 全量包地址
}bundleStatus 说明原生包登记状态:matched 完全匹配;rebuiltSameJs 同 JS 指纹但构建时间不同(只允许全量);unknownBundle 指纹未登记(严格渠道下保持当前版本)。
元数据与崩溃报告关联
import * as Sentry from '@sentry/react-native';
import { attachToSentry, getUpdateMetadata } from 'rn-update';
// 在已有 Sentry 初始化之后调用。
attachToSentry(Sentry);
const metadata = getUpdateMetadata();getUpdateMetadata() 返回当前更新版本信息(含 currentVersion),updateMetadataTags() 生成可直接挂到 Sentry tags 的键值对。
错误与事件
UpdateError携带稳定的机器可读code(UpdateErrorCode)。EventData(logger回调)包含type(如checking、downloading、downloadSuccess、rollback、markSuccess、errorUpdate…)与错误详情。JS 错误上报与堆栈还原见 JS 报错监控。
Crashlytics 需向 attachToCrashlytics(reporter) 传入已初始化且提供 setAttribute/setAttributes 的实例。默认标签前缀为 pakta.,当前更新标签为 pakta.currentVersion。
checkUpdate(params?)
在 UpdateProvider 的子组件中调用。检查后会更新 updateInfo,并执行所选更新策略,可能继续下载或弹窗。
checkUpdate(params?: { extra?: { toHash?: string } }): Promise<CheckResult | undefined>不传参数检查当前设备可用的更新。extra.toHash 用于测试指定更新,不用于设置渠道。跳过检查时可能返回 undefined;失败默认记录到 lastError,配置 throwError: true 后可以捕获异常。
const { checkUpdate, lastError } = useUpdate();
async function onCheck() {
const info = await checkUpdate();
if (!info) return;
if (info.expired) {
// 当前安装包需要升级,下载地址在 info.downloadUrl。
return;
}
if (info.paused) return;
if (info.upToDate) return;
if (info.update) {
// 后续下载和生效行为取决于 updateStrategy。
}
}只想取得原始检查结果、自行画界面时使用 client.checkUpdate(),不要同时调用 Provider 和 client 两套检查流程。完整手动示例见自定义更新界面。
downloadUpdate(info?)
downloadUpdate(info?: CheckResult): Promise<boolean | undefined>info 默认是最近一次检查结果。没有可下载更新时返回 false;成功完成 Provider 下载流程时返回 true。afterDownloadUpdate 返回 false 时也返回 false,即使文件已经下载。
const { updateInfo, downloadUpdate } = useUpdate();
async function onDownload() {
if (!updateInfo?.update) return;
const completed = await downloadUpdate(updateInfo);
if (!completed) return;
}Provider 的这个方法会继续执行下载后的策略:silentAndNow 请求立即重载,silentAndLater 安排下次启动,其余情况可能显示生效提示。不要把它当成“只下载文件”的接口。
只下载时调用 client.downloadUpdate(info, onProgress?):返回 Promise<string | undefined>,字符串是下载完成的更新 hash;然后自己调用 client.switchVersion(hash) 或 client.switchVersionLater(hash)。
downloadAndInstallApk(url)
下载完整 Android 安装包并打开系统安装界面,用于需要升级原生版本的情况。它不安装 .ppk,也不负责 iOS 或 HarmonyOS 安装。
downloadAndInstallApk(url: string): Promise<void>| 项目 | 要求 |
|---|---|
url | 可直接下载的 HTTPS APK 地址,不是商店网页或 AAB |
| 平台 | Android;其他平台跳过 |
| 安装包 | 与当前 App 包名和签名匹配,版本符合系统升级要求 |
| 返回值 | 无;Promise 完成不代表用户已确认安装 |
| 错误 | 默认在 lastError 中;throwError: true 时可用 try/catch |
1. 添加安装权限
在 App 的 android/app/src/main/AndroidManifest.xml 中,放到 <manifest> 内、<application> 外:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />重新构建并分发安装包,权限不会通过 JS 更新加入。SDK 使用 Android 系统安装会话,不需要额外添加 FileProvider。HTTP 地址会被拒绝。
2. 添加升级按钮
下面组件放在现有 UpdateProvider 下。apkUrl 由业务传入实际 APK 下载地址,也可以来自检查结果的 downloadUrl。
import { useState } from 'react';
import { Button, Platform, Text, View } from 'react-native';
import { useUpdate, useUpdateProgress } from 'rn-update';
export function NativeUpgradeButton({ apkUrl }: { apkUrl: string }) {
const { downloadAndInstallApk, lastError } = useUpdate();
const progress = useUpdateProgress();
const [busy, setBusy] = useState(false);
const [error, setError] = useState('');
async function install() {
if (busy || !apkUrl) return;
setBusy(true);
setError('');
try {
await downloadAndInstallApk(apkUrl);
} catch (cause) {
setError(cause instanceof Error ? cause.message : String(cause));
} finally {
setBusy(false);
}
}
if (Platform.OS !== 'android') return null;
const percent = progress?.hash === 'downloadingApk' && progress.total > 0
? Math.round(progress.received / progress.total * 100)
: undefined;
return (
<View>
<Button title={busy ? '正在下载' : '升级安装包'}
disabled={busy || !apkUrl} onPress={() => { void install(); }} />
{percent !== undefined ? <Text>{percent}%</Text> : null}
{error || lastError ? <Text>{error || lastError?.message}</Text> : null}
</View>
);
}3. 处理系统授权和安装结果
Android 8 及以上需要允许当前 App 安装未知来源应用。权限未开启时,SDK 尝试打开系统设置,并报告 APK_INSTALL_PERMISSION_REQUIRED。用户允许后回到 App,再点升级按钮。
下载过程中重复调用会跳过。已经下载并等待安装时,再调用可能得到 APK_INSTALL_PENDING;让用户完成系统安装,不要循环下载。权限已允许但安装失败时,检查 APK 是否完整、包名、签名和版本号。
如果发布渠道要求通过商店更新,使用业务自己的商店跳转,不调用 APK 安装方法。
markSuccess()
确认当前更新已经能正常使用,结束此次新版本启动的回滚保护。
markSuccess(): Promise<boolean | undefined>返回 true 表示原生层接受确认;false 表示拒绝;已确认、开发环境或不在新版本首次启动时可能返回 undefined。原生调用失败会抛错。
默认 Provider 在挂载后约 1000 ms 自动确认。只有需要等关键页面或初始化完成时才关闭自动确认:
autoMarkSuccess: false,const { markSuccess } = useUpdate();
async function confirmReady() {
try {
const accepted = await markSuccess();
if (accepted === false) {
// 未接受确认,保留诊断信息。
}
} catch (error) {
// 展示或记录确认失败,不要当成已成功。
}
}不要在刚下载完时确认:要确认的是新版本启动成功。已确认后的任意业务异常不一定触发自动回滚。
currentVersionInfo
currentVersionInfo: {
name?: string;
description?: string;
metaInfo?: string;
} | null表示当前运行更新的名称、说明和自定义数据。updateInfo 则是最近检查到的候选更新,两者不要混用。
const { currentVersionInfo, currentHash, packageVersion } = useUpdate();
const label = currentVersionInfo?.name || '安装包自带版本';currentHash 为空表示正在使用安装包自带的 JS。packageVersion 是原生安装包版本,不会因为热更新名称变化而改变。
getCurrentVersionInfo()
getCurrentVersionInfo(): Promise<{
name?: string;
description?: string;
metaInfo?: string;
}>兼容旧代码的异步方法,新代码直接读取 currentVersionInfo。
const { getCurrentVersionInfo } = useUpdate();
const version = await getCurrentVersionInfo();restartApp()
restartApp(): Promise<void>请求原生层重启 React Native 应用环境。它不会检查或下载更新,也不保证操作系统杀掉整个 App 进程。调用前保存草稿、支付状态等必要数据。
const { restartApp } = useUpdate();
await restartApp();调用前执行 beforeReload({ type: 'restartApp' }),返回 false 取消重启。钩子或原生重启失败会抛错,应在按钮回调中捕获。
resetToPackagedBundle(options?)
清除已下载更新和本地更新状态,恢复安装包自带的 JS,保留设备标识。它不是选择某个历史热更新。
resetToPackagedBundle(options?: { restart?: boolean }): Promise<boolean | undefined>const { resetToPackagedBundle } = useUpdate();
const reset = await resetToPackagedBundle({ restart: true });
if (!reset) {
// 重置没有成功,不要向用户显示“已恢复”。
}默认不立即重启,下次启动加载内置包;restart: true 会在重置后请求重启。返回 true 只表示重置成功,重启可能被钩子取消或失败。Web 返回 false;不支持此原生方法的旧安装包会报告 RESET_FAILED。服务端仍发布相同更新时,后续检查可能再次下载,运营应先停止问题版本。
switchVersion(info?)
switchVersion(info?: CheckResult): Promise<boolean | undefined>立即切换到已经下载的更新,参数默认最近检查结果。无 hash 时跳过;返回 true 表示已请求原生重载,不能当成新版本已正常启动。
const { switchVersion, updateInfo } = useUpdate();
if (updateInfo?.hash) await switchVersion(updateInfo);必须先下载。该方法执行 beforeReload,返回 false 可取消;当前页面会在重载时中断。调用客户端实例对应的方法时传 hash 字符串:client.switchVersion(hash)。
switchVersionLater(info?)
switchVersionLater(info?: CheckResult): Promise<void>把已下载更新设为下次启动使用的版本,保持当前页面。无 hash 时跳过,不触发 beforeReload。
const { switchVersionLater, updateInfo } = useUpdate();
if (updateInfo?.hash) await switchVersionLater(updateInfo);测试时完整关闭并重新启动 App,仅切换页面不算重启。客户端实例用法为 client.switchVersionLater(hash)。
parseTestQrCode(code)
parseTestQrCode(code: string | UpdateTestPayload): boolean接受扫码得到的 JSON 字符串或对象。返回 true 只表示识别了测试载荷,不代表下载或生效成功。
const { parseTestQrCode } = useUpdate();
const accepted = parseTestQrCode({
type: '__rnPaktaVersionHash',
data: '替换成控制台里目标更新的完整 hash',
});识别后会检查指定更新;仍需观察后续检查结果。testChannel: false 拒绝测试载荷。扫码组件由业务提供,SDK 不会替你打开摄像头。
使用已有 App 深链时,可传 ?type=__rnPaktaVersionHash&data=HASH,Provider 会读取查询参数。原生 scheme 仍需在工程中配置并重新构建。扫码测试与安装包里的固定渠道是两个设置。
useUpdateProgress()
import { Text } from 'react-native';
import { useUpdateProgress } from 'rn-update';
export function DownloadProgress() {
const data = useUpdateProgress();
if (!data) return null;
const percent = data.progress ?? (data.total > 0
? Math.round(data.received / data.total * 100) : undefined);
return <Text>{percent === undefined ? '正在下载' : `${percent}%`}</Text>;
}返回 ProgressData | undefined:received / total 为字节数,progress 是可选的 0–100 百分比。APK 进度可能只有字节数;未知总量时显示下载中。仅需进度的组件用此 Hook,可减少其他更新状态变化带来的渲染。
dismissError()
清空 Provider 的 lastError,不会重试或改变已下载的内容。
const { lastError, dismissError } = useUpdate();
// 在用户关闭错误提示时调用 dismissError()。需要自动清除时,把 dismissErrorAfter: 5000 加入现有客户端配置,单位毫秒。
自定义更新界面
实例的 checkUpdate / downloadUpdate 用于自己控制流程。它们和 Hook 方法的参数、返回值不同:实例下载返回 hash,实例切换接受 hash。
import { useState } from 'react';
import { Button, Text, View } from 'react-native';
import { useUpdate } from 'rn-update';
export function ManualUpdateButton() {
const { client } = useUpdate();
const [busy, setBusy] = useState(false);
const [message, setMessage] = useState('');
async function update() {
if (!client || busy) return;
setBusy(true);
try {
const info = await client.checkUpdate();
if (!info?.update) {
setMessage(info?.expired ? '请升级安装包' : '暂无可下载更新');
return;
}
const hash = await client.downloadUpdate(info, (data) => {
setMessage(data.progress === undefined ? '正在下载' : `${data.progress}%`);
});
if (!hash) return;
await client.switchVersionLater(hash);
setMessage('下载完成,下次启动生效');
} catch (error) {
setMessage(error instanceof Error ? error.message : String(error));
} finally {
setBusy(false);
}
}
return <View>
<Button title="检查并下载" disabled={busy} onPress={() => { void update(); }} />
<Text>{message}</Text>
</View>;
}配套把 checkStrategy: null、throwError: true 加入现有客户端。checkStrategy 只关闭 JS 自动检查;需要同时关闭原生后台检查时另设 disableNativeCheck: true,并接受失去原生救援能力的影响。
检查、下载和重载钩子
| 配置 | 收到什么 | 返回值如何影响流程 |
|---|---|---|
beforeCheckUpdate | 无参数 | false 跳过本次检查 |
afterCheckUpdate | { status, result?, error? } | 记录检查完成、跳过或失败,不替换结果 |
beforeDownloadUpdate | CheckResult | false 跳过下载 |
afterDownloadUpdate | CheckResult | false 停止 Provider 下载后的提示或切换 |
onPackageExpired | CheckResult | false 阻止内置原生升级处理 |
beforeReload | { type, hash? } | false 取消立即重载;抛错也不继续 |
这些配置都加入根组件外的已有客户端。比如在立即重载前等待业务保存:
beforeReload: async ({ type }) => {
if (type === 'switchVersion') {
const saved = await savePendingDrafts();
return saved;
}
return true;
},savePendingDrafts 是业务自己的保存函数,应返回是否可以继续。等待操作设置合理超时,避免更新按钮永久等待。
原生启动检查
disableNativeCheck 默认关闭,即原生检查启用。它在 App 冷启动后独立检查更新,JS 不能运行时也能下载修复。
checkStrategy: null 不会关闭这次网络请求;服务端 forceBoot 可以安排修复在后续启动生效。本地已回滚版本仍受保护。操作入口见强制救砖。
captureException(error, context?)
使用已有客户端记录业务捕获的 JS 异常,无需再创建一个实例:
const { client } = useUpdate();
try {
await submitOrder();
} catch (error) {
client?.captureException(error, { context: 'checkout' });
}未捕获 JS 错误默认自动上报;disableErrorReporting 单独关闭错误上报,disableTelemetry 也会阻止相关传输。上下文只放诊断所需信息。对应 sourcemap 的归档和还原见报错监控。
Android 混编:setCustomInstanceManager
已有原生 Android 工程自己维护 ReactInstanceManager、没有标准 ReactApplication 时,把同一个正在使用的实例交给 SDK,供重载使用:
import cn.reactnative.modules.update.UpdateContext;
UpdateContext.setCustomInstanceManager(reactInstanceManager);在创建该实例后调用。它不代替 bundle 路径配置,构建实例时仍需使用 UpdateContext.getBundleUrl(context);标准 React Native 工程按原生接入即可,无需额外创建实例。
