更新记录
1.0.1(2026-06-16) 下载此版本
cf-uniwebview 接入说明
cf-uniwebview 用来在 App 内打开原生 WebView,并向页面注入一层统一的 JSBridge,方便 H5 和宿主 App 双向通信。
当前插件只支持:
APP-IOSAPP-ANDROID
目录结构
- 插件入口:index.uts
- 类型定义:interface.uts
- H5 Bridge 工具:webview-bridge.js
- iOS 实现:app-ios/index.uts
- Android 实现:app-android/index.uts
- Android 原生主体:app-android/CFUniWebViewAndroidPlugin.kt
- 当前项目的业务包装层:services/native/webview-plugin.uts
说明:
webview-bridge.js是 H5 侧 helper,内部仍然依赖原生在页面加载时注入到window的 bridge。- 普通浏览器 / 普通 H5 环境里如果没有原生注入,helper 会返回
bridge_unavailable。
插件导出
插件本体目前只导出两个方法:
isSupported() : boolean
openWebUrlWithOptions(
options : WebViewOpenOptions,
callback : (result : WebViewBridgePayload) => void
) : boolean
类型定义见 interface.uts:
export type WebViewBridgePayload = {
action ?: string | null
data ?: any | null
message ?: string | null
}
export type WebViewOpenOptions = {
platformName ?: string | null
platformCode ?: string | null
linkUrl ?: string | null
token ?: string | null
customUserAgent ?: string | null
channel ?: string | null
openMode ?: string | null
origin ?: boolean | null
animated ?: boolean | null
fullscreen ?: boolean | null
topBarHidden ?: boolean | null
applyDialogWindowConfig ?: boolean | null
patchChooseImage ?: boolean | null
}
其中当前代码里已经实际生效的字段主要是:
platformNameplatformCodelinkUrltokencustomUserAgentopenModeanimatedfullscreentopBarHiddenapplyDialogWindowConfig:仅 Android 生效patchChooseImage:仅 Android 生效
当前版本里 channel、origin 还没有在原生实现中实际使用,建议视为保留字段。
App 侧用法
推荐像当前项目一样,业务层不要直接四处调用插件本体,而是加一层自己的包装。
当前项目包装层在:
它已经帮业务做了这些事情:
- 自动补
platformName - 自动补
platformCode - 自动补
token - 相对路径自动拼接
AUTH_BASE_URL - 对运行环境做了可用性判断
当前项目调用示例
import { openNativeWebView } from '@/services/native/webview-plugin.uts'
openNativeWebView({
linkUrl: '/h5/order/detail?id=123',
customUserAgent: 'your-ua',
topBarHidden: false,
openMode: 'present',
animated: true,
fullscreen: true,
applyDialogWindowConfig: true,
patchChooseImage: true
}, (res : any) => {
console.log('webview callback =', res)
})
直接调用插件示例
import { isSupported, openWebUrlWithOptions } from '@/uni_modules/cf-uniwebview'
import { WebViewOpenOptions, WebViewBridgePayload } from '@/uni_modules/cf-uniwebview/utssdk/interface.uts'
export function openNativeWebView(
options : WebViewOpenOptions,
callback : ((result : WebViewBridgePayload) => void) | null = null
) : boolean {
if (!isSupported()) {
return false
}
return openWebUrlWithOptions(
options,
callback == null
? (_ : WebViewBridgePayload) : void => {}
: callback
)
}
参数说明
linkUrl:打开的网页地址,不能为空platformName:传给 H5 的平台名称platformCode:传给 H5 的平台编码token:传给 H5 的 tokencustomUserAgent:附加到 WebView UA 的自定义标识openMode:present或pushanimated:是否带打开/关闭动画fullscreen:present模式下是否全屏topBarHidden:是否隐藏原生顶部栏applyDialogWindowConfig:Android 下是否套用弹窗 window 配置patchChooseImage:Android 下是否接管 H5 内的uni.chooseImage()
打开结果回调
H5 调 plugWebView() 主动关闭并回传:
{
action: 'plugWebView',
data: {
success: true,
orderId: '123456'
}
}
H5 调 postMessageToApp() 持续发消息:
{
action: 'postMessage',
data: {
type: 'stepChange',
step: 2
}
}
用户主动点关闭:
{
action: 'dismiss'
}
打开失败或原生错误:
{
action: 'error',
message: 'invalid_url'
}
H5 侧用法
推荐直接引用:
import Bridge, {
getPlugData,
getDeviceInfo,
getLocation,
getLoaction,
openAppSettings,
openNativeUrl,
postMessageToApp,
copyText,
getImageFromPhotoLibrary,
takePhoto,
saveImageToLibrary,
callPhone,
plugWebView
} from '@/uni_modules/cf-uniwebview/utssdk/webview-bridge.js'
webview-bridge.js 内部仍然依赖原生注入到 window 的这些全局方法:
window.WebViewJavascriptBridgewindow.setupWebViewJavascriptBridgewindow.getPlugDatawindow.getDeviceInfowindow.getLocationwindow.getLoactionwindow.openAppSettingswindow.postMessageToAppwindow.copyTextwindow.getImageFromPhotoLibrarywindow.takePhotowindow.saveImageToLibrarywindow.callPhonewindow.plugWebViewwindow.openNativeUrl
最直接的用法示例:
window.getDeviceInfo(function (info) {
console.log('deviceInfo =', info)
})
也可以走标准 bridge 形式:
window.WebViewJavascriptBridge.callHandler('getPlugData', null, function (data) {
console.log('plugData =', data)
})
说明:
- 当前原生注入层本身是 callback 风格。
- 如果业务想用 Promise,建议在 H5 项目里自行封一层 helper。
一个最小 Promise 包装示例
function callBridge(name, data) {
return new Promise(function (resolve) {
if (!window.WebViewJavascriptBridge) {
resolve({ success: false, message: 'bridge_unavailable' })
return
}
window.WebViewJavascriptBridge.callHandler(name, data || null, function (res) {
resolve(res)
})
})
}
const plugData = await callBridge('getPlugData')
H5 能力清单
1. 获取 App 注入参数
window.getPlugData(function (plugData) {
console.log(plugData)
})
通常会包含:
platformNameplatformCodelinkUrltokenopenModeanimatedfullscreentopBarHiddenapplyDialogWindowConfig:Android 会带上patchChooseImage:Android 会带上
2. 获取设备信息
window.getDeviceInfo(function (deviceInfo) {
console.log(deviceInfo)
})
3. 获取定位
window.getLocation(function (res) {
console.log(res)
})
兼容旧拼写:
window.getLoaction(function (res) {
console.log(res)
})
成功示例:
{
success: true,
locationSuccess: true,
errorMsg: '',
latitude: 31.2304,
longitude: 121.4737,
accuracy: 35,
location: {
latitude: '31.2304',
longitude: '121.4737'
}
}
常见失败值:
location_permission_deniedlocation_provider_disabledlocation_timeoutlocation_busy
4. 打开系统设置
window.openAppSettings(function (res) {
console.log(res)
})
5. 打开外部链接
window.openNativeUrl({
url: 'weixin://',
fallbackUrl: 'https://weixin.qq.com/'
}, function (res) {
console.log(res)
})
支持这些字段:
urlfallbackUrlfailOpenUrlbackupUrl
6. 给 App 发消息但不关闭页面
window.postMessageToApp({
type: 'progress',
value: 50
}, function (res) {
console.log(res)
})
7. 关闭页面并回传数据
window.plugWebView({
success: true,
orderId: '123456'
})
8. 复制文本
window.copyText({ text: 'abc123' }, function (res) {
console.log(res)
})
也支持直接传字符串:
window.copyText('abc123', function (res) {
console.log(res)
})
9. 从相册选图
window.getImageFromPhotoLibrary(function (res) {
console.log(res)
})
需要 base64 时:
window.getImageFromPhotoLibrary({
returnBase64: true
}, function (res) {
console.log(res)
})
返回示例:
{
success: true,
fileName: 'image.jpg',
mimeType: 'image/jpeg',
size: 12345,
tempFilePath: '/.../cache/xxx-image.jpg',
base64: 'data:image/jpeg;base64,...'
}
10. 拍照
window.takePhoto(function (res) {
console.log(res)
})
需要 base64 时:
window.takePhoto({
returnBase64: true
}, function (res) {
console.log(res)
})
返回结构和 getImageFromPhotoLibrary() 对齐。
11. 保存图片到相册
window.saveImageToLibrary({
url: 'https://example.com/test.jpg'
}, function (res) {
console.log(res)
})
支持这些输入:
- 远程图片 URL
data:image/...;base64,...content://...file://...- 本地绝对路径
成功示例:
{
success: true,
savedUri: 'content://...',
fileName: 'image.jpg',
mimeType: 'image/jpeg',
size: 12345
}
12. 拨打电话
window.callPhone({
phoneNumber: '13800138000'
}, function (res) {
console.log(res)
})
也支持:
window.callPhone('13800138000', function (res) {})
window.callPhone({ mobile: '13800138000' }, function (res) {})
window.callPhone({ tel: '13800138000' }, function (res) {})
window.callPhone({ phone: '13800138000' }, function (res) {})
直接使用 JSBridge
如果不走全局快捷方法,也可以直接调用:
window.WebViewJavascriptBridge.callHandler('getPlugData', null, cb)
window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, cb)
window.WebViewJavascriptBridge.callHandler('getLocation', null, cb)
window.WebViewJavascriptBridge.callHandler('openAppSettings', null, cb)
window.WebViewJavascriptBridge.callHandler('openUrl', { url: 'weixin://' }, cb)
window.WebViewJavascriptBridge.callHandler('postMessageToApp', { type: 'x' }, cb)
window.WebViewJavascriptBridge.callHandler('copyText', { text: 'abc123' }, cb)
window.WebViewJavascriptBridge.callHandler('getImageFromPhotoLibrary', { returnBase64: true }, cb)
window.WebViewJavascriptBridge.callHandler('takePhoto', { returnBase64: true }, cb)
window.WebViewJavascriptBridge.callHandler('saveImageToLibrary', { url: 'https://example.com/test.jpg' }, cb)
window.WebViewJavascriptBridge.callHandler('callPhone', { phoneNumber: '13800138000' }, cb)
window.WebViewJavascriptBridge.callHandler('plugWebView', { success: true }, cb)
平台差异
Android
- 使用
WebViewClientURL 拦截形式实现 bridge customUserAgent会和系统默认 UA 合并applyDialogWindowConfig仅 Android 生效patchChooseImage: true时会显式 patchuni.chooseImage()- 已接通:定位、相册选图、拍照、保存到相册、拨号、Web 媒体权限处理
- 自带加载态和失败态页面
iOS
- 使用注入脚本 + 轮询信号形式实现 bridge
- 支持
present和push fullscreen控制模态展示样式- 对
tel:/uni.makePhoneCall做了 bridge 接管 - 已接通:定位、相册选图、拍照、保存到相册、打开设置、拨号
常见错误码
通用
bridge_unavailableinvalid_urlactivity_unavailableunsupported
定位
location_permission_deniedlocation_provider_disabledlocation_timeoutlocation_busylocation_unavailable
相册 / 图片
picker_busypicker_unavailableinvalid_imageimage_permission_deniedcancel
拍照
camera_permission_deniedcamera_unavailablecamera_busy
保存图片
invalid_image_urlsave_permission_deniedsave_failedsave_busy
拨号
invalid_phone_numbercall_permission_deniedcall_unavailablecall_busy
权限说明
Android Manifest
当前插件声明了这些权限:
android.permission.INTERNETandroid.permission.CALL_PHONEandroid.permission.CAMERAandroid.permission.RECORD_AUDIOandroid.permission.ACCESS_FINE_LOCATIONandroid.permission.ACCESS_COARSE_LOCATIONandroid.permission.READ_MEDIA_IMAGESandroid.permission.READ_EXTERNAL_STORAGEandroid.permission.WRITE_EXTERNAL_STORAGEmaxSdkVersion="28"
文件位置:
新增权限后,需要重新打自定义基座或重新打包,纯热更新不会生效。
iOS
iOS 侧涉及:
- 定位权限
- 相册读取权限
- 相册写入权限
- 相机权限
如果目标项目要独立复用这个插件,记得同步补齐对应的 Info.plist 权限文案。
其他项目复用建议
如果要在别的 uni-app x 项目复用,建议最少做这几步:
- 复制整个
uni_modules/cf-uniwebview目录。 - 在目标项目新建自己的包装层,不要让业务代码直接依赖插件本体。
- 在包装层里补默认的域名、平台标识、token、UA。
- 按目标项目实际情况补齐 Android 权限和 iOS 权限描述。
- 如果 H5 侧想使用 Promise,再在 H5 项目里封一层自己的 helper。
1.0.0(2026-06-13) 下载此版本
cf-uniwebview 接入说明
cf-uniwebview 用来在 App 内打开原生 WebView,并给 H5 提供一层统一 JSBridge。
当前仓库里它分成两部分:
- App 侧打开入口:webview-plugin.uts
- H5 Bridge 工具:webview-bridge.js
原生实现位置:
App 侧用法
打开网页
import { openNativeWebView } from '@/services/native/webview-plugin.uts'
openNativeWebView({
linkUrl: 'https://example.com',
platformName: 'xxxxxx',
platformCode: 'accountbutler',
customUserAgent: 'your-ua',
topBarHidden: false,
openMode: 'present',
animated: true,
fullscreen: true
}, (res : any) => {
console.log('webview callback =', res)
})
参数说明
linkUrl: 打开的地址platformName: 传给 H5 的平台名platformCode: 传给 H5 的平台编码token: 传给 H5 的 tokencustomUserAgent: 自定义 UAtopBarHidden: 是否隐藏原生导航栏openMode:'present'或'push'animated: 是否带动画fullscreen: 是否全屏模态展示origin: 原样透传给 H5 的扩展字段
App 回调
H5 关闭并回传:
{
action: 'plugWebView',
data: {
success: true,
orderId: '123456'
}
}
H5 持续发消息:
{
action: 'postMessage',
data: {
type: 'stepChange',
step: 2
}
}
用户主动关闭:
{
action: 'dismiss'
}
H5 侧用法
推荐直接使用:
import {
getPlugData,
getDeviceInfo,
getLocation,
getLoaction,
openAppSettings,
openNativeUrl,
postMessageToApp,
copyText,
getImageFromPhotoLibrary,
takePhoto,
saveImageToLibrary,
callPhone,
plugWebView
} from '@/uni_modules/cf-uniwebview/utssdk/webview-bridge.js'
这些方法同时支持:
- Promise 风格
- callback 风格
例如:
const info = await getDeviceInfo()
getDeviceInfo((info) => {
console.log(info)
})
H5 能力清单
获取 App 传参
const plugData = await getPlugData()
通常会返回:
platformNameplatformCodelinkUrltokentopBarHiddenfullscreenopenModeanimatedorigin
获取设备信息
const deviceInfo = await getDeviceInfo()
获取定位
const location = await getLocation()
兼容旧拼写:
const location = await getLoaction()
成功示例:
{
success: true,
locationSuccess: true,
errorMsg: '',
latitude: 31.2304,
longitude: 121.4737,
accuracy: 35,
location: {
latitude: '31.2304',
longitude: '121.4737'
}
}
常见失败值:
location_permission_deniedlocation_provider_disabledlocation_timeoutlocation_busy
打开系统设置页
await openAppSettings()
打开外部链接
await openNativeUrl({
url: 'weixin://',
fallbackUrl: 'https://weixin.qq.com/'
})
支持:
urlfallbackUrlfailOpenUrlbackupUrl
给 App 发消息但不关闭页面
await postMessageToApp({
type: 'progress',
value: 50
})
关闭页面并回传
await plugWebView({
success: true,
orderId: '123456'
})
复制文本
await copyText('abc123')
从相册选图
const image = await getImageFromPhotoLibrary()
需要 base64:
const image = await getImageFromPhotoLibrary({
returnBase64: true
})
返回示例:
{
success: true,
fileName: 'image.jpg',
mimeType: 'image/jpeg',
size: 12345,
tempFilePath: '/.../cache/xxx-image.jpg',
base64: 'data:image/jpeg;base64,...'
}
拍照
const photo = await takePhoto()
需要 base64:
const photo = await takePhoto({
returnBase64: true
})
返回结构和 getImageFromPhotoLibrary() 对齐。
保存图片到相册
await saveImageToLibrary({
url: 'https://example.com/test.jpg'
})
支持这些输入:
- 远程图片 URL
data:image/...;base64,...content://...file://...- 本地绝对路径
成功示例:
{
success: true,
savedUri: 'content://...',
fileName: 'image.jpg',
mimeType: 'image/jpeg',
size: 12345
}
拨打电话
await callPhone({
phoneNumber: '***'
})
也支持:
await callPhone('***')
await callPhone({ mobile: '***' })
await callPhone({ tel: '***' })
await callPhone({ phone: '***' })
直接使用 JSBridge
如果不想引入 webview-bridge.js,也可以直接调用:
window.WebViewJavascriptBridge.callHandler('getPlugData', null, cb)
window.WebViewJavascriptBridge.callHandler('getDeviceInfo', null, cb)
window.WebViewJavascriptBridge.callHandler('getLocation', null, cb)
window.WebViewJavascriptBridge.callHandler('openAppSettings', null, cb)
window.WebViewJavascriptBridge.callHandler('openUrl', { url: 'weixin://' }, cb)
window.WebViewJavascriptBridge.callHandler('postMessageToApp', { type: 'x' }, cb)
window.WebViewJavascriptBridge.callHandler('copyText', { text: 'abc123' }, cb)
window.WebViewJavascriptBridge.callHandler('getImageFromPhotoLibrary', { returnBase64: true }, cb)
window.WebViewJavascriptBridge.callHandler('takePhoto', { returnBase64: true }, cb)
window.WebViewJavascriptBridge.callHandler('saveImageToLibrary', { url: 'https://example.com/test.jpg' }, cb)
window.WebViewJavascriptBridge.callHandler('callPhone', { phoneNumber: '***' }, cb)
window.WebViewJavascriptBridge.callHandler('plugWebView', { success: true }, cb)
平台说明
Android
- 使用 WebView URL 拦截形式实现桥接
getLocation()已接通,并带权限申请getImageFromPhotoLibrary()已接通takePhoto()已接通saveImageToLibrary()已接通callPhone()已接通- 内嵌 H5 的
uni.chooseImage()已做原生兜底
iOS
- 使用注入脚本 + 轮询信号形式实现桥接
openNativeUrl({ url: 'tel://' })可用于拨号callPhone()内部也是复用openNativeUrl打开tel://- 图片、定位、保存图片等能力已接通
常见错误码
通用
bridge_unavailable: 当前不在原生 WebView 环境,或桥尚未注入完成invalid_url: 传入的链接无效activity_unavailable: 当前原生页面或宿主上下文不可用
定位
location_permission_denied: 定位权限被拒绝location_provider_disabled: 系统定位服务未开启location_timeout: 定位超时location_busy: 已有一个定位请求正在进行location_unavailable: 当前设备无法提供定位能力
相册 / 图片
picker_busy: 已有一个选图流程正在进行picker_unavailable: 当前设备无法拉起系统选图invalid_image: 图片读取失败或返回内容无效image_permission_denied: 图片读取兜底权限被拒绝cancel: 用户取消了选图
拍照
camera_permission_denied: 相机权限被拒绝camera_unavailable: 当前设备无法拉起系统相机camera_busy: 已有一个拍照流程正在进行
保存图片
invalid_image_url: 图片地址为空或格式不支持save_permission_denied: 保存图片权限被拒绝save_failed: 保存到系统相册失败save_busy: 已有一个保存流程正在进行
拨号
invalid_phone_number: 手机号为空或格式无效call_permission_denied: 电话权限被拒绝call_unavailable: 当前设备无法发起拨号call_busy: 已有一个拨号流程正在进行
权限说明
Android Manifest
当前插件会用到这些权限:
android.permission.INTERNETandroid.permission.CALL_PHONEandroid.permission.CAMERAandroid.permission.ACCESS_FINE_LOCATIONandroid.permission.ACCESS_COARSE_LOCATIONandroid.permission.READ_MEDIA_IMAGESandroid.permission.READ_EXTERNAL_STORAGEandroid.permission.WRITE_EXTERNAL_STORAGEmaxSdkVersion="28"
新增权限后,需要重新打自定义基座或重新打安装包,纯热更新不会生效。
iOS
图片、相机、定位、电话能力都依赖系统本身的权限或能力状态,请同步检查宿主工程的权限说明文案。
平台兼容性
uni-app x(4.21)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| × | × | 7.0 | 13 | - | × |

收藏人数:
下载插件并导入HBuilderX
赞赏(0)
下载 7
赞赏 0
下载 12425752
赞赏 1934
赞赏
京公网安备:11010802035340号