UserAgent
Native会定制浏览器的 UserAgent 的值,在末尾添加一段字符串,逗号拼接,H5可split或正则式判断。
host
=gyyx-mobile
// 运行在 移动端APP WebView中
app-name
=cos // 应用名称:cos
, lns
, xfx
app-ver
=1.36.2 // 应用版本
os-type
=iOS // 系统统类型:iOS
, Android
os-version
=12.2 // 系统版本, 安卓端是 API Level
status-height
=44 // 状态栏高度(留海高度)
比如 iOS WebView的 UserAgent 内容:
"Mozilla/5.0 AppleWebKit host=gyyx-mobile,os-type=iOS,app-name=cos,app-ver=1.57,os-version=14.6,status-height=44"
navigator.userAgent.split(/\s+/).pop().split(',').reduce((acc,curr)=> {
const [k, v=''] = curr.split('=');
acc[k] = v;
return acc
}, {})
输出结果:
注意,APP使用的dsBridge有个限制:函数只能有一个参数,和一个回调(如果异步)。
参数的类型是string, 多个参数需要JSON.stringify({ k1: xxx, k2: yyy }) 。下文中 “参数:” 后面加了大括号的(参数:{...} ),需要JSON.stringify() 。
回调的参数也是string类型。下文中 “返回:” 后面加了大括号的(返回: {...} ), 需要JSON.parse() 。
建议使用 Typescript 版本的Bridge,它封装了dsBridge和JSON解析,参数类型定义清晰,方便易用。
网络请求
httpRequest
参数:
{
url: 'https://app.gxcospower.cn/app_v1/account/user/logoff/reason/type/list'
method: 'GET', // 默认'GET'。其他还有 POST, PATCH, PUT, DELETE
params: { k1: xxx, k2: yyy } , // 请求参数,可选
encode: 'form', // 默认'form'。还可以是'json'。 当method为GET/DELETE时,可忽略此参数
headers: { token: xxxx } , // 可选
}
界面交互
showLoading
显示loading,还有一个类似的API: loadingShown
hideLoading
隐藏loading, 还有一个类似的API: loadingHidden
showModal
参数:
{
title: string // 非必填,但 title 和 content 至少要填一个
content: string // 非必填,但 title 和 content 至少要填一个
contentAlignCenter: boolean // 内容文本水平居中?, 默认 false, 居左
showCancel: boolean // 默认 true
cancelText: string //默认 '取消'
cancelColor: string // 默认'#333333'
confirmText: string // 默认 '确定'
confirmColor: string // 默认 APP主题色
}
返回字符串: 'confirm'
或 'cancel'
showToast
参数:
{
title:string,
style: string // 'success' | 'error' | 'info' ,默认 info
duration: number // 毫秒,默认 2000
}
图片相关
previewImage
全屏预览图片,支持手势缩放、滑动切换
参数:
{
imageUrls: ['url1', 'url2'...],
index: 0 // 初始预览的索引。可选,默认0,第一张
}
saveImage
保存图片到相册
参数:
{
imageUrls: ['url1', 'url2'...], // 或者
imageBase64: 'base64 string', // base64格式 只支持一张图
}
返回:
{
success: boolean,
message: '...reason...' // 失败原因
}
pickImage
采集照片
参数:
{
source?: number, // 照片来源,0:相册, 1:相机,2:让用户选择相机或相册。 默认相册
crop?: boolean, // 是否需要裁剪
cropRate?: number, // 如果需要裁剪,裁剪区域的高宽比,高/宽。(宽度是屏幕宽度)
label?: string, // 为图片指定一个标识。后续要上传时,会用到此标识。
}
返回:
{
success: boolean,
data: '...base64String...', // base64格式
}
注意:原生会对照片做压缩处理:单张照片最大不超过300K, 宽或高最大1080p,超过则缩小至此值(等比缩小)
uploadImage
上传图片
参数:
{
label: string, // 图片标识
folder?: string, // 目录(图片上传的目录)
service?: string, // 存储服务
}
返回:
{
success: boolean,
data: 'http://path/to/image', // 图片url
}
playVideo
播放视频
参数:
{
url: 'http://..../...mp4' // 视频链接
}
数据存储
sessionStorage.setItem
参数:{ key1: val1, key2: val2, ... }
sessionStorage.getItem
参数: key名称
sessionStorage.removeItem
参数: key名称
localStorage.setItem
参数:{ key1: val1, key2: val2, ... }
localStorage.getItem
参数: key名称
localStorage.removeItem
参数: key名称
注意:localStorage是持久存储,重启APP后不会丢失。 sessionStorage是临时存储,重启APP后会丢失。
存储能用来传递数据,比如原生和H5约定用“userInfo”做为key存取用户信息,原生存入,H5读出。反之亦然。
事件通知
emitter.on
监听事件。
参数:
{
name: "事件名称",
listener: "回调函数名称", // 通过dsBridge.register注册 回调函数。
tag: '自定义标签' , // 可选,传递给回调函数的 额外参数。
func: (arg:string) => void; // Typescript版本+,可免除显式register注册。
}
注意:目前一个事件只能关联一个回调函数,重复监听会发生覆盖。
emitter.off
取消监听。
参数:
{
name: "事件名称",
listener: "回调函数名称",// Typescript版本+
}
emitter.emit
发出事件。
参数:
{
name: "事件名称",
args: "事件参数",// 可选。多个参数可逗号拼接,或k1=v1&k2=v2, 或JSON.stringify({ k1: v1 })
}
H5发出的事件,原生能监听到; 原生发出的事件,H5也能监听到。 浏览器A中的H5发出的事件,浏览器B中的H5也能监听到。
环境参数或公共参数建议使用特殊命名,可以是大写或下划线,比如 来源页面,参数:_source_
前后加下划线,以区别普通参数。
窗口控制
window.open
新开浏览器窗口,
参数:
{
url: 'https://.....',
windowId: 'xxx', //窗口ID, 用于标识窗口。可选
option: 'redirect', // 目前只支持一个值:redirect. 可选。
}
option: 'redirect': 页面A -> 页面窗口B,如果在B打开C时,使用了redirect,那么从C返回前一页时,会返回到A(不再是B).
常用场景是 第三方Web页面,如 微信文章,xx客服,xx商场,xx问卷调查 等,或者 技术实现不同,如 在React页面中打开jQurey实现的页面
注意:如果url值以 file:// 开头,会被认为是本地路径,尝试加载本地html文件
window.close
关闭浏览器窗口
参数:
{
windowId: 'xxx', // 目标窗口ID, 可选
serial: boolean, // 关闭连续的浏览器窗口,可选
}
如果不传参数,就关闭当前浏览器窗口
windowId: 从右向左查找相应windowId的Web窗口(可跨越非Web窗口),找到就显示此窗口(关闭其右侧的所有窗口),若找不到,则不做任何动作。 返回失败: {success:false,message:'未找到目标ID窗口'}
serial: 从右向左关闭Web窗口,只到不是Web窗口为止,如果第一个窗口也是Web窗口,则不做任何动作。返回失败:{success:false, message:'未找到非Web窗口'}
window.setProps
设置窗口属性
参数:
{
windowId: string // 窗口ID, 可选
backgroundColor: '#FAFAFA', // 底色,可选
}
window.setGoBack
定制返回行为, 参数:回调函数名称 (通过dsBridge.register注册)
// Typescript版本,使用第2个参数 可以免除显式register注册函数
function setGoBack(label: string, func?: () => void)
window.resetGoBack
恢复自然返回
返回行为:点击页面左上角的【返回】,或者从屏幕左边缘向右扫,或者按物理键返回(某些安卓手机有),
默认行为都是 返回上一页。但 原生APP的上一页 和 浏览器的上一页 不是一个概念。浏览器的上一页是历史回溯,history.back(),还能前进,history.forward(),而 原生返回上一页,当前页就彻底消失了。站在H5的角度理解,就是原生的每一页就相当于一个独立的浏览器,返回上一页就是把当前浏览器关闭了,其history 自然也随之消失。
为了使返回行为更为自然,原生先检查浏览器能否返回,若能,就调用浏览器的hostory.back(), 若不能,则走原生的返回,也就是关闭浏览器,暂时称这种返回方式为「自然返回」。
自然返回能满足大多数情况,然而有例外,比如 返回时提示:“......,确定返回吗?”,这时可以 定制返回行为(setGoBack),传入自定义函数,即 告诉原生:当返回行为触发时,不要自然返回,而是调用自定义函数。
代码示例:
// 指定(返回时调用的)函数名称:myBack
Bridge.window.setGoBack('myBack', () => {
if (confirm('确定返回吗?')){
Bridge.window.close() // 或 history.go(-1)
}
);
特殊参数
特殊的 url查询参数,前后缀下载线,拼接在url后面(? | &)。
_hidenavbar_
隐藏页面导航栏。(导航栏是有标题 和 返回按钮 的那一栏)
只要url中出现这个参数:
_hidenavbar_
,就表示要隐藏,无论其值是什么
_hidenavbar_
=0 // 0, 1, 2, 3
它的值 指定 状态栏 的样式。(状态栏是有电池电量、信号强度 的那一栏):
0 :隐藏状态栏,非0 不隐藏
1: 状态栏前景色 白色
2: 状态栏前景色 黑色
3: 状态栏前景色 默认
_title_
指定页面标题。
不再取html中的<title>
,而是使用url中的_title_
参数的值做为页面标题.
注意:如果标题中包含中文,要经过 url编码。
window.onblur
当窗口将要不可见时(被新窗口覆盖,或退后台),原生将调用H5注册的 window.onblur 函数。
window.onfocus
当窗口可见或重新可见时(覆盖窗口消失,或回前台),原生将调用H5注册的 window.onfocus 函数。
页面初次加载完毕时,也会调用window.onfocus, 同时传入一个值为'loadFinish'
的字符串参数。
注意:onblur和onfocus不是必需的,不注册也不会有问题。
backToHome
回首页
backPreviousPage
参数:
{
checkHistory: true, // 先尝试history.back(),如果不可以,就关闭WebView窗口。默认false
}
返回前一页
navigateTo
页面导航
参数:
{
url: 'app://xxx',
option: 'redirect', // 目前只支持一个值:redirect. 可选。(其作用 参考window.open)
}
和window.open不同,这里的url值是原生APP定义的页面路由,符合URL规则,可拼接查询参数.
对于换电APP,有一个特殊的路由:app://offline/[business]/[entry] ,意思是让原生APP导航到本地H5页面。
business指定业务模块,entry指定模块入口
navigateBack
页面返回
参数:
{
route: 'app//xxx' // 页面路由
}
existRoute
导航栈中是否存在某页面
参数:
{
route: 'app//xxx' // 页面路由
}
如果存在,返回“YES”, 否则 “” (空串)
presentMask
创建一个全屏透明浏览器窗口,遮罩在现有页面上方。
参数:
{
url: "app://offline/<business>/<entry>",// business指定业务模块,entry指定模块入口
}
遮罩中的页面加载一定要快,为保证速度,这里不允许在线加载,只允许本地、离线加载。
dismissMask
关闭全屏遮罩,同时还可以附加一个动作,比如 导航至某页面,或打开浏览器,或广播事件。
参数:
{
navUrl: string; // 页面导航路径,同 navigateTo 的 url 参数。
navOpt: string; // 页面导航选项,同 navigateTo 的 option 参数。
winOpenUrl: string; // 打开浏览器窗口的链接,同 window.open 的 url 参数。
winOpenOpt: string; // 打开浏览器窗口的选项,同 window.open 的 option 参数。
emitName: string; // 发出事件的名称, 同 emitter.emit 的 name 参数。
emitArg: string; // 发出事件的参数, 同 emitter.emit 的 args 参数。
}
注意:可以不附加动作。如果要附加动作,只能附加一个,即 页面导航、打开浏览器、发出事件 三选一。
这个API的使用场景略微特殊:展示H5页面的浏览器(WebView)被做成一个 全屏的、透明的 浮层,覆盖在原页面上,达到的效果是 既能看到H5页面内容,也能看到(被覆盖在下面的)原页面内容。 比如 用H5实现一个弹框,覆盖在原生APP页面上,看上去就像原生实现的弹框。 而要关闭全屏透明的浏览器浮层,就要用到dismissMask。
设备功能
getDeviceInfo
设备信息
返回:
{
equipmentId: "设备ID",
appVersion: "应用版本",
appType: "应用类型",
osType: "操作系统类型",
systemVersion: "操作系统版本",
deviceModel: "设备型号",
mac: "Mac地址",
deviceBrand: "设备品牌",
oaid: "安卓设备标识",
androidid: "安卓ID",
platform: "平台类型",
deviceOs: "设备操作系统",
deviceId: "设备ID",
channel: "应用渠道",
idfa: "广告ID",
}
scanQRcode
扫码
参数:
{
notice: string; // 扫码页面上的 提示文案。比如 '请扫描担保二维码'
showAlbum?: boolean; // 是否显示 相册按钮,默认false
showNoCodeExchange?: boolean; // 是否显示 无码换电 按钮, 默认false
}
返回:
{
code: string, // 二维码的值
action: string, // 动作名称(用户没有扫码,而是点击了页面上的按钮(比如 【无码换电】)。
}
注意:code和action互斥。只会一个有值,另一个是空字符串。
目前 action只有一个取值:'noCodeExchange'
copyText
复制文本(至系统剪贴板)
参数:文本
callPhone
拨打电话
参数:电话号码
另: tel://18621529129,也应该可以拨打电话。
比如:
<a href="tel://18621529129">
联系某人
navigation
第三方导航
参数:
{
longitude: "经度",
latitude: "纬度",
address: "地址名称"
}
拉起的是Native中的第三方导航弹层,Native会检测当前设备中安装了哪些第三方导航软件,Android最多且仅支持拉起(高德、百度、腾讯),iOS最多且仅支持拉起(高德、百度、苹果);
联系客服
contactService
对于换电APP,它会弹出一个菜单(在线客服、电话客服)
支付宝支付
tradePay
参数:
{
orderStr:string; // 接口返回的订单号
}
返回:
{
resultStatus:string // 支付状态值
}
注意:虽然可以判断resultStatus,但有例外:用户不点支付宝的【确定】或【放弃】返回APP,而是通过Home键切换应用的方式 返回APP,这会导致无法回调resultStatus。推荐方式是监听窗口事件(window.onfocus),手动轮询支付结果。
微信分享
appShare
参数:
{
title: string //卡片标题
link: string //跳转目标链接,如果不是http开头,就用当前页面的url后面拼接这个值做为目标链接
imgUrl: string //卡片图片logo
desc: string //卡片描述
}
用户登录
appLogin
参数:自定义对象。
Native登录完成后(登录页关闭),会发一个事件通知:USER_LOGIN_SUCCESS, 参数是 token 值
// H5 监听用户登录事件,注册回调,回调函数的参数就是token值
Bridge.emitter.on({
name: 'USER_LOGIN_SUCCESS',
listener: 'onLoginSuccess',
func: (token: string) => {
// 根据 token 请求数据
}
});
Native同时会在本地存储中设置token值,key为 APP_USER_TOKEN。 退出登录时,也会清空token值。
// Native APP端 设置:
localStorage.setItem('APP_USER_TOKEN', token)// H5端无需设置,原生APP会设置
// H5 获取:
const token = Bridge.localStorage.getItem('APP_USER_TOKEN')
跟踪事件(埋点)
trackEvent
参数:
{
name: "事件名称",
type: "事件类型",
category: "分类",
params: { key1: val1, key2: val2, ... }
}
params是个对象,可选,其属性和属性值 目前仅支持string类型
注意:在换电APP中,categroy的值是“lingGe”时,表示灵鸽埋点(取name),否则是普通埋点(取name+type)
这些API如何使用,有Demo示例么?
作者回复: 有的,可参考:https://jvlian.cn/static/bridge/ds.html 这个是使用dsbridge原始方式调用的,还有一份TS封装版,本文档中部分示例使用了TS封装版本。