@epochx/android-native-bridge
v1.0.0
Published
Secure iOS WKWebView and Android WebView H5 bridge SDK with ESM, typed feature modules and browser-global bundles.
Maintainers
Readme
@epochx/android-native-bridge
面向 Android WebView 和 iOS WKWebView 内嵌 H5 的 Promise 风格 Native Bridge SDK,提供 ESM、TypeScript 类型、按功能拆分的子路径入口和浏览器 UMD 单文件。
可靠安装
pnpm 用户建议安装后显式执行一次幂等初始化,确保不受依赖生命周期脚本拦截或缓存影响:
pnpm add @epochx/android-native-bridge
pnpm exec native-app init初始化会:
- 向当前项目的
package.json补充缺失的android:*命令。 - 仅在项目根目录不存在配置时创建
native-app.config.json。 - 按
android.signing.dir创建签名目录,默认是android/signing。 - 保留已有配置和已有命令;同名命令不一致时只提示冲突,不会覆盖。
- 将构建、签名、渠道和 H5 热更新工具保留在依赖包内,不向项目复制脚本。
pnpm 10+ 可能拦截未获准依赖的生命周期脚本。如需后续安装时自动执行 postinstall,可按 pnpm 提示批准本包:
pnpm approve-builds @epochx/android-native-bridgenpm 用户可直接安装;禁用生命周期脚本时再显式初始化:
npm install @epochx/android-native-bridge
npm exec native-app init初始化后至少填写 project.brandName、project.applicationId、web.prodUrl 和 web.testUrl,然后检查配置:
pnpm run android:config:check
pnpm run android:doctorH5 热更新:直接使用
首次使用先生成 H5 热更新密钥;该命令通常只执行一次:
pnpm android:h5-signing测试服热更新
pnpm android:hot-update -- --version=2608021051 --build-script=build:test --message="测试服更新内容"默认模板中 build:test 等于 web.testBuildScript,因此自动:
- 执行
pnpm run build:test。 - 将
dist打成versions/android/debug/2608021051/dist.zip。 - 签名并写入项目根目录
versions/android/debug/versions.json。 - 从
android.hotUpdate.packageBaseUrl自动拼接下载地址<base>/debug/2608021051/dist.zip。
若业务项目使用其他测试构建命令,建议明确指定环境:
pnpm android:hot-update -- --version=2608021051 --build-script=build:staging --metadata-channel=debug --message="测试服更新内容"正式服热更新
pnpm android:hot-update -- --version=2608021051 --message="本次更新内容"不传 --build-script 时使用 native-app.config.json#web.prodBuildScript,并自动写入 versions/android/release/versions.json;ZIP 写入 versions/android/release/<版本>/dist.zip。
首次使用需在 native-app.config.json#android.hotUpdate.packageBaseUrl 配置 HTTPS 基础路径。命令只需输入一次 --version;该值同时作为 ZIP 的父目录名和元数据版本。正确发布顺序是:生成 ZIP 和元数据 → 按生成目录上传 ZIP → 部署对应的 versions.json。
热更新参数
| 参数 | 是否必填/默认值 | 说明 |
| --- | --- | --- |
| --version | 必填 | 热更新版本,只允许递增数字及 .、_、- 分段,例如 2608021051 或 2026.8.2.1。 |
| --package-url | 配置覆盖 | 紧急兼容用的 ZIP 最终 HTTPS 地址;正常发布无需传。 |
| --base-url | android.hotUpdate.packageBaseUrl | 临时覆盖配置中的 HTTPS 基础路径。 |
| --build-script | web.prodBuildScript | 要执行的 package script,例如 build:test。等于 web.testBuildScript 时默认写 debug 元数据。 |
| --metadata-channel | 自动推断 | debug 或 release;也接受 test、prod 别名。显式值优先于构建命令推断。 |
| --metadata-output | versions/android/<环境>/versions.json | 完全覆盖元数据输出位置,一般无需设置。 |
| --dist | web.distDir | H5 构建产物目录,必须包含 index.html。 |
| --output | android.hotUpdate.outputDir | Android 热更根目录,默认模板为 versions/android。 |
| --message | 发现新的页面版本 | 客户端展示的更新说明。含空格时需要引号。 |
| --min-native-version-code | 1 | 允许安装该热更新的最低 Android versionCode。 |
| --min-bridge-version | 0.0.1 | 最低 Bridge 协议版本。 |
| --max-bridge-version | 空 | 最高 Bridge 协议版本;为空表示不限制。 |
| --force | false | 是否标记为强制更新,可写 --force 或 --force=true。 |
| --skip-build | false | 跳过 H5 构建,直接使用现有 dist,适合 CI 已完成构建的场景。 |
| --build-env | 空 | 临时传给构建命令的环境变量,例如 --build-env=API_ENV=test,FEATURE_X=true。 |
| --private-key | 自动读取 .env.h5-update-signing | 临时覆盖 H5 热更新私钥路径,通常无需传入。 |
| --overwrite | false | 显式允许重新发布同一版本;默认拒绝覆盖 ZIP 或不递增的元数据。 |
查看命令内置帮助:
pnpm android:hot-update -- --helpandroid:h5-signing 和 android:signing 的区别
| 命令 | 签名对象 | 生成内容 | 什么时候需要 |
| --- | --- | --- | --- |
| pnpm android:h5-signing | H5 热更新 ZIP/versions.json | RSA 私钥、公钥、.env.h5-update-signing | 使用 H5 热更新前必须执行,通常首次生成后持续复用。 |
| pnpm android:signing | Android APK/AAB | JKS、证书指纹、.env.android-signing | 构建可安装或上架的 release 壳时必须执行。 |
两个命令不能合并为同一把密钥:Android 安装包由系统/应用商店验证 JKS,H5 热更新由壳内置公钥验证 RSA 签名;分开可以独立轮换和吊销,也能避免一把密钥泄露同时影响壳和热更新。如果业务项目只生成 H5 热更、不负责构建 Android release 壳,可以不执行 android:signing,但依赖包仍需保留该命令供壳发布使用。
配置文件
初始化会在项目根目录生成 native-app.config.json。项目字段默认留空,Android 通用目录、签名、渠道和热更新约定保留默认值。
| 字段 | 默认值/要求 | 说明 |
| --- | --- | --- |
| schemaVersion | 1,必填 | 配置结构版本,目前固定为 1。 |
| project.brandName | 空字符串,必填 | 应用展示名称,映射到原生品牌名。 |
| project.applicationId | 空字符串,必填 | Android applicationId/packageName。 |
| project.storageNamespace | 空字符串 | 本地存储命名空间。 |
| project.deepLinkScheme | 空字符串 | Deep Link scheme。 |
| project.deepLinkHost | 空字符串 | Deep Link host。 |
| web.prodUrl | 空字符串,必填 | H5 正式环境地址。 |
| web.testUrl | 空字符串,必填 | H5 测试环境地址。 |
| web.prodBuildScript | build:prod | 正式 H5 构建命令。 |
| web.testBuildScript | build:test | 测试 H5 构建命令。 |
| web.distDir | dist | H5 构建输出目录。 |
| android.requiredJavaFiles | 通用 Java 文件列表 | android:doctor 检查的原生文件。 |
| android.hotUpdate.apiPath | /api/app/hot-update | 未配置 packageBaseUrl 时使用的兼容接口路径。 |
| android.hotUpdate.allowedHosts | [] | 允许下载更新的主机列表。 |
| android.hotUpdate.outputDir | versions/android | Android 元数据和热更新包的共同根目录。 |
| android.hotUpdate.packageBaseUrl | 空字符串,发布前必填 | ZIP 和 versions.json 的 HTTPS 基础路径;壳构建自动选用 <base>/release/versions.json 或 <base>/debug/versions.json,源码模板不包含业务地址。 |
| android.hotUpdate.archivePrefix | app | 旧版兼容字段;新包按环境输出为 <环境>/<版本>/dist.zip。 |
| android.hotUpdate.privateKeyFile | h5-update-private.pem | H5 热更新私钥文件名。 |
| android.hotUpdate.publicKeyFile | h5-update-public.pem | H5 热更新公钥文件名。 |
| android.signing.dir | android/signing | Android 主签名、渠道签名和 keystore 的统一目录;不存在时自动创建。 |
| android.signing.keystoreFile | app-upload.jks | Android 主 keystore 文件名。 |
| android.signing.keyAlias | app | keystore key alias。 |
| android.signing.distinguishedName | 通用 Android DN | 新证书的 distinguished name。 |
| android.signing.backupPrefix | app | 签名备份文件名前缀。 |
| android.build.outputDir | android/releases | APK/AAB 输出目录。 |
| android.build.outputPrefix | app | 安装包文件名前缀。 |
| android.build.versionHistoryFile | android/releases/version-history.json | 按渠道保存 versionCode 和每次成功发布的产物历史。 |
| android.build.defaultChannel | official | 默认渠道,必须存在于渠道列表。 |
| android.channels[].id | 至少一项,必填 | 小写字母开头,仅允许小写字母和数字。 |
| android.channels[].flavor | 可选 | 对应 Android product flavor。 |
| android.channels[].label | 必填 | 渠道展示名称。 |
签名文件生成
H5 热更新优先执行:
pnpm android:h5-signing它会在 android.signing.dir 中生成 .env.h5-update-signing、H5 RSA 私钥和公钥,并按需创建 versions/android/release/versions.json。debug 元数据会在测试热更生成时创建到 versions/android/debug/versions.json。
发布 APK/AAB 时再生成 Android 应用签名:
pnpm android:signing该命令在同一签名目录生成 JKS、随机强密码、证书指纹和 .env.android-signing。渠道独立签名使用:
pnpm android:signing:channel -- --channel=official签名脚本不会静默覆盖已有文件;重新生成时会要求确认并备份旧签名。签名文件、密码和私钥禁止提交到版本库,应立即分别做离线加密备份。
渠道列表
native-app.config.json 中的 android.channels 是唯一渠道列表,不再创建或读取 .android-custom-channels.json。
交互式执行 pnpm run android:build 并选择“新增自定义渠道”时,工具会询问渠道 ID 和名称,然后直接向当前配置文件的 android.channels 追加:
{
"id": "partner",
"flavor": "custom",
"label": "Partner"
}也可以手工修改该数组。渠道 ID 长度为 1–32,必须以小写字母开头且只允许小写字母和数字;flavor 必须对应 Android 已有 product flavor,自定义渠道默认使用 custom。
每次渠道构建会读取 android.build.versionHistoryFile:已有渠道使用上次成功出包的 versionCode + 1,首次出包使用 --version-code、环境变量 ANDROID_VERSION_CODE 或自动时间基线。--all-channels 会分别计算并记录每个渠道,APK/AAB 全部生成成功后才原子追加该渠道的历史记录。
快速使用
推荐导入 /auto,它会根据运行环境安装 Android 或 iOS Bridge:
import { appNativeBridge } from "@epochx/android-native-bridge/auto";
import {
getAppNativeBridge,
isAppNativeBridgeAvailable,
} from "@epochx/android-native-bridge";
if (isAppNativeBridgeAvailable()) {
const bridge = getAppNativeBridge();
console.log(await bridge?.getDeviceInfo());
}/auto 会安装 window.AppNativeBridge。根入口不主动安装运行时,只提供实例读取、底层创建器、协议常量、错误类型和视口工具。
原生通道
Android 必须在 H5 执行 SDK 前注入一个带 postMessage(string) 的 JavaScript channel。SDK 按顺序查找:
window.NativeBridgeChannelwindow.LeanLinkNativeChannelwindow.NativeBridgeChannelLegacy
iOS 使用 window.webkit.messageHandlers 中的原生消息通道,具体接入见 iOS 使用说明。普通浏览器和 Tauri 环境不会被识别为本 SDK 的原生运行时。
能力检测
可选能力必须通过 supportsCommand() 或 getCapabilities().commands 检测,不要使用 userAgent 推断:
if (await appNativeBridge?.supportsCommand("native_capture_screenshot")) {
const image = await appNativeBridge.captureScreenshot();
}能力表获取失败时,supportsCommand() 返回 false。
生物识别认证
Android 壳使用系统 BiometricPrompt 完成指纹/人脸认证,生物特征数据不会传给 H5。可选择允许设备 PIN/图案/密码降级:
if (await appNativeBridge?.supportsCommand("native_authenticate_biometric")) {
const result = await appNativeBridge.authenticateBiometric({
title: "确认本人操作",
allowDeviceCredential: true,
});
console.log(result.authenticationType);
}同一时间只允许一个认证请求。用户取消返回 BIOMETRIC_CANCELLED;未录入生物特征返回 BIOMETRIC_NOT_ENROLLED。
API 分组
- 应用与设备:
getCapabilities、getAppInfo、getDeviceInfo、getSystemDirectories、getStorageConfig、ensureDirectory、clearDirectory - 语言与主题:系统语言、主题和状态栏样式
- 媒体与文件:媒体设备、录音、文件选择、相册、相机和截图
- 通知与推送:通知权限、通知设置、本地通知、通知动作、推送注册和冷启动动作恢复
- 系统能力:网络、设置、外链、分享、震动、剪贴板、文件保存/打开、弹窗、重启和退出
- 权限与导航:通用权限、内置/外部浏览器和页面路由
- 第三方能力:定位、支付、生物识别、JPush 和 BLE 外设
- Android 扩展:开屏广告和预置应用图标
- H5 热更新:检查、安装、首屏确认、回滚和状态查询
完整方法、参数和返回类型见 H5 接入与使用手册,原生命令契约见 ANDROID_COMMANDS.md。
按需导入
根入口和 /auto 提供完整 facade。需要控制包体或自行组装运行时时,可按需导入:
import { createBridgeClient } from "@epochx/android-native-bridge/core";
import { createAndroidWebViewChannelAdapter } from "@epochx/android-native-bridge/runtime/android-webview";
import { installSystemFeatures } from "@epochx/android-native-bridge/features/system";
const adapter = createAndroidWebViewChannelAdapter(window);
const bridge = createBridgeClient({
getChannel: () => adapter.getChannel(),
});
installSystemFeatures(bridge);可用子路径包括:
/core、/protocol、/facade/runtime/android-webview、/runtime/ios-wkwebview、/runtime/viewport/features/app、media、notifications、system、update/features/device、permission、ui-router、file、location/features/pay-biometric、third-sdk、jpush、ble-peripheral、system-enhance
纯 /core 不访问 window,可在 SSR 或 Node 环境安全导入。
调用与回包协议
H5 发给原生:
{
"id": "native-...",
"command": "native_get_device_info",
"args": {
"request": {}
}
}原生可通过以下任一方式回包:
window.AppNativeBridge.receive({ id, ok: true, result: {} });
window.AppNativeBridge.receive({ id, ok: false, error: "permission denied" });
window.AppNativeBridge.resolve(id, result);
window.AppNativeBridge.reject(id, error);默认调用超时为 60 秒,可通过底层入口覆盖:
await appNativeBridge?.invoke("native_long_task", {}, {
timeoutMs: 120_000,
});屏幕、键盘与安全区
Android 和 iOS 运行时会安装视口同步能力,监听原生视口事件、resize、orientationchange、Screen Orientation 和 Visual Viewport。
标准化结果可从以下位置读取:
window.__LEANLINK_VIEWPORT__document.documentElement.dataset.screenOrientation--app-viewport-width、--app-viewport-height--app-keyboard-inset-bottom--app-safe-area-inset-top|right|bottom|leftLeanLinkViewportChange事件
也可以直接使用运行时 API:
import {
installViewportMetrics,
readViewportMetrics,
} from "@epochx/android-native-bridge/runtime/viewport";宿主应传递真实的系统栏、键盘和内容区 inset;H5 应避免对宿主已排除的 inset 重复补偿。
H5 热更新
await appNativeBridge?.installH5Update({
currentVersion: "1.0.0",
reload: true,
});
await appNativeBridge?.confirmH5UpdateReady();生产更新源应由原生宿主固定。manifest 和更新包必须经过 HTTPS 来源白名单、RSA-SHA256 签名、SHA-256、大小、Bridge 版本、解压限额和回滚校验。
通知能力前置条件
getPushRegistration()依赖 Android FCM 或 iOS APNs 的原生配置;未配置时应返回supported=false。getFullScreenIntentPermission()和openFullScreenIntentSettings()仅适用于支持该能力的 Android 版本。setAppBadge()的显示效果取决于 Android 启动器或 iOS 系统支持。- SDK 只负责 H5 与原生之间的桥接,不替代推送供应商、商店权限声明、服务端凭据或原生实现。
浏览器单文件
无构建工具的页面可使用包内 mobile-native-bridge.umd.js。将该文件复制到静态资源目录后加载:
<script defer src="/assets/mobile-native-bridge.umd.js"></script>就绪后使用 window.AppNativeBridge,或监听:
window.addEventListener("AppNativeBridgeReady", ({ detail: bridge }) => {
void bridge.getAppInfo();
});core.js、commands.js、boot.js 和 bridge-basic-all.js 仅作为旧版 script 标签兼容入口保留。新接入推荐 ESM 或 mobile-native-bridge.umd.js。
安全与兼容性
- 调用可选能力前始终进行能力检测。
- 不允许 H5 动态覆盖生产更新源或原生安全策略。
- 文件、通知、定位、相机、麦克风和系统设置等操作必须由原生层执行权限检查。
- 运行环境与版本要求见 COMPATIBILITY.md。
- 来源、权限与更新安全要求见 SECURITY.md。
文档
许可证
MIT
