# 前端接口
微社区自研浏览器 SDK 包括 Android 与 iOS 版,2 个版本都覆写了浏览器的 alert、confirm、prompt 弹框,并提供了统一的 JS 接口
# 接入指引
# 前端页面添加 JS 文件
<script
type="text/javascript"
src="https://ossweb-img.qq.com/images/js/ingame_sdk/browser_adapt.js"
></script>
<script>
if (typeof customBrowserInterface == 'object') {
/*只有使用微社区自研浏览器SDK才能访问全局变量customBrowserInterface,使用其他浏览器打开微社区时customBrowserInterface为undefined*/
}
</script>
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 前端页面添加返回按钮,用于返回上一页或返回游戏。
在 browser_adapt.js 里暴露了全局变量 customBrowserInterface
的一组接口,使用 demo 可参考 使用 Demo
为了避免出现白屏,加载第一个页面时会出现菊花状的进度条
# 微社区自研浏览器 SDK 的兼容性
- Android 下兼容 X5 浏览器、系统自带的 WebView,优先使用 X5 浏览器,加载 X5 浏览器失败时就使用系统自带的 WebView
- 使用 X5 浏览器时需指定 activity 的 android:process=":ingame_inner_webview",采用新进程来启动 X5 浏览器,不然会获取 JNIEnv 失败
- iOS 下兼容 UIWebView、WKWebView,iOS8.2 及后续版本使用 WKWebView(从 iOS8 开始才有 WKWebView,iOS8.2 之前会偶现白屏问题),其他版本使用 UIWebView
- 覆写了浏览器的 prompt 弹框(传特定 JSON 格式的参数时不会出现 prompt 弹框),JS 与 SDK 之间的交互通过 prompt 来实现,因此 browser_adapt.js 中的接口的返回值都是字符串
- 调用 browser_adapt.js 中的接口时,如果 SDK 中没有对应的接口,就会返回空串 "",以此可以处理 JS 与 SDK 之间的兼容性
JS 与 SDK 之间的交互通过 prompt 来实现的原因如下:
- Android 下可用 WebView 的 addJavascriptInterface 来暴露接口给 JS,但 Android4.2 之前通过反射机制 JS 可访问任意 java 类的函数,存在安全漏洞
- iOS7 之前在 UIWebView 的 shouldStartLoadWithRequest 里处理交互,但 JS 调用无法获取返回值;iOS7 及后续版本的 UIWebView 可用 JavaScriptCore,JS 调用能获取返回值
- iOS8 及后续版本可以使用 WKWebView,但 JS 调用无法获取返回值
- 微社区的 JS 调用浏览器接口时需获取返回值,考虑到安全性、兼容性以及代码的可维护性,JS 与 SDK 之间的交互通过 prompt 来实现
- 特别注意:Android 下 onJsPrompt 在主线程中运行(可直接修改 UI,但需新起子线程执行网络操作),而 iOS 下 runJavaScriptTextInputPanelWithPrompt 不是在主线程中运行(不能直接修改 UI)
- 加载大图时(不管是 img 还是 canvas),Android 下的 WebView、iOS 下的 UIWebView 都会内存飙升,而 iOS 下的 WKWebView 内存基本无变化(WKWebView 是一个多进程组件,网络资源加载、UI 渲染都是在其他进程中执行,因此看上去似乎不占内存)
- 频繁使用 prompt 与 SDK 交互时,SDK 的接口即使不做任何处理 iOS 下的 UIWebView、WKWebView 都会内存飙升,Android 下 的 WebView 内存基本无变化
注:Android(Java,通过 NDK 访问 C++)、iOS(Objective-C,直接访问 C++)、Unity(C#,最终会转换为 C++ 代码,也可以通过 DllImport 访问 C++),公共的代码可用 C++ 开发,各种平台都可以用,MSDK 就是这种方式
使用过程中遇到了任何问题请 RTX 联系:faniuxu(徐发牛)
# API
# 获取浏览器版本
customBrowserInterface.getCustomUserAgent()
//注:腾讯视频播放器会根据navigator.userAgent来判断如何播放视频,为了不干扰视频播放,修改navigator.userAgent时只是在末尾添加了空格 + 自定义串("Android TIEM Ingame Browser/0.5"、"iOS TIEM Ingame Browser/0.5",其中0.5为版本号,会动态变化)
customBrowserInterface.getVersion()
//判断customBrowserInterface.getCustomUserAgent()的返回值中的版本号,微社区自研浏览器SDK根据这个版本号来实现各版本之间的兼容
1
2
3
4
5
2
3
4
5
# 是否是微社区自研浏览器
customBrowserInterface.isCustomBrowser()
//返回值:true: 是 ; false: 不是
1
2
2
# 分享到 QQ 空间
customBrowserInterface.sendToQQ(1, title, desc, url, imgUrl)
//注:第一个参数固定为1,其他参数依次为标题、描述、点击后的跳转链接、图片的url,从第二个参数开始如果不需要某个参数可置为空串"",而不是null。
//如果没有出现分享界面,请检查imgUrl是否以"https://"开头,iOS下的app默认不允许直接加载http资源
1
2
3
2
3
# 分享给 QQ 好友
customBrowserInterface.sendToQQ(2, title, desc, url, imgUrl)
//注:第一个参数固定为2,其他参数请参考"分享到QQ空间"
1
2
2
# 分享到微信朋友圈
customBrowserInterface.sendToWeixinWithUrl(1, title, desc, url, imgUrl)
//注:第一个参数固定为1,其他参数请参考"分享到QQ空间",微信分享有很多限制,比如缩略图不能超过32kb等,具体限制可以查看微信官方文档:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317332&token=&lang=zh_CN
1
2
2
# 分享给微信好友
customBrowserInterface.sendToWeixinWithUrl(2, title, desc, url, imgUrl)
//注:第一个参数固定为2,其他参数请参考"分享到QQ空间"
1
2
2
# 是否装了微信
customBrowserInterface.isPlatformInstalled(1)
//返回值:"1": 安装了; "0": 没有安装
1
2
2
# 是否装了 QQ
customBrowserInterface.isPlatformInstalled(2)
//返回值:"1": 安装了; "0": 没有安装
1
2
2
# 登录的帐号类型
customBrowserInterface.getAccountType()
//返回值:"1": 微信"; 2": QQ; 其他值: 未知
1
2
2
# 实时获取当前的网络状态
customBrowserInterface.getNetworkType()
//返回值: "NO NETWORK"、"WIFI"、"4G"、"3G"、"2G"、"UNKNOWN NETWORK"
1
2
2
# 当前的操作系统
customBrowserInterface.isAndroid()
//返回值:"1": Android; "0": iOS
1
2
2
# 关闭浏览器返回游戏
customBrowserInterface.closeWebview()
1
# 查看设备信息
customBrowserInterface.getDeviceInfo()
/*返回值:
Android下的返回值: '{"osSystem":"", "osVersion":"", "deviceModel":"", "deviceName":"", "deviceTradeMark":"", "deviceManufacturer":"", "uid":"", "memoryUpperLimit":进程的内存上限(单位为K), "usedMemory":当前进程占用内存(单位为K), "processCpuTime":当前进程占用的CPU时间, "totalCpuTime":总的CPU时间, "dalvikMemory":Java代码占用的内存(单位为K), "nativeMemory":C/C++代码占用的内存(单位为K), "otherMemory":其他内存(单位为K)}'
iOS下的返回值: '{"osSystem":"", "osVersion":"", "deviceModel":"", "uid":"", "deviceName":"", "physicalMemory":手机总的内存(单位为K), "usedMemory":当前进程占用内存(单位为K), "cpuUsageRatio":当前进程的CPU使用率(不带百分号的数值,如:3.1表示3.1%)}'
注:返回值是JSON格式的字符串,iOS下在UIWebView中频繁调用此接口会导致内存飙升,WKWebView无此问题
【1】Android下当"usedMemory + 新分配的内存 ≥ memoryUpperLimit"就会出现OOM(out of memory),iOS下当"usedMemory / physicalMemory ≥ 百分比值(不同系统这个值不一样)"时进程会被杀死,参考文献"https://stackoverflow.com/questions/5887248/ios-app-maximum-memory-budget"
【2】Android下的CPU使用率 = (这次获取的processCpuTime - 上次获取的processCpuTime) / (这次获取的totalCpuTime - 上次获取的totalCpuTime)
*/
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 生成快捷方式
// Android下的调用方式:
customBrowserInterface.addShortcut(name, imgUrl, url)
// iOS下的调用方式:
customBrowserInterface.addShortcut(url)
// 注:name是快捷方式的名称,imgUrl是快捷方式的图标的url,Android下的url是快捷方式跳转的链接地址,iOS下的url是获取mobileconfig文件的链接地址。
// iOS下生成快捷方式是用Safari加载mobileconfig文件,根据mobileconfig文件进行安装,安装完毕就生成了快捷方式。
// Android下生成快捷方式不同于iOS,无需安装,但不一定会成功,部分手机禁止生成快捷方式,部分手机会被手机管家阻止,需要通过手机管家里的权限管理进行配置
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 上传图片
customBrowserInterface.imagePicker()
/*
返回图片的base64编码,图片的格式为JPEG,为了防止占用太多内存,会对图片进行压缩(尺寸不变,存储空间变小),如果没有选择任何图片就会返回空串""
使用demo:
<img id="iosImg" height="200" width="200" />
document.getElementById("iosImg").src = "data:image/jpeg;base64," + customBrowserInterface.imagePicker();
*/
1
2
3
4
5
6
7
2
3
4
5
6
7
# RSA 非对称加密
// 客户端只知道公钥,服务端只知道私钥
//【1】用公钥加密客户端的请求
var publicKey =
'-----BEGIN PUBLIC KEY-----\n' +
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDzgSvQ4btonPCt1IOalue2N6i4\n' +
'ABozjeC1rmmAY/ZcafPXsoafoTSgiJ1chF9ZQ/4Woc7eEkcTboenIiD58CjiFYfm\n' +
'g05fZm3uqCpTT6Ht3qUhkEBS9PzjgP96gjUJ18am+m+jUzkABF7ow1EEmoaK4Q20\n' +
'leneGrOt4uw+tJRbOwIDAQAB\n' +
'-----END PUBLIC KEY-----'
var encrypted = customBrowserInterface.encrypt('客户端的请求', publicKey)
//【2】用公钥解密服务端的响应
var decrypted = customBrowserInterface.decrypt(
'用私钥加密的服务端响应',
publicKey
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 微信委托授权(.qq.com 下的页面才允许拉起微信委托授权)
// 微社区接入论坛时,为了打通各游戏的论坛帐号,需要将游戏的openid转换成论坛的openid,前提是需要拉起微信委托授权
customBrowserInterface.delegateLogin(游戏的微信Appid)
// 注意:如果在原生代码里传递了游戏的微信Appid,delegateLogin函数传递的微信Appid就会被忽略
1
2
3
2
3
# H5 页面给游戏发消息(需要游戏配合)
customBrowserInterface.sendToGame('XXX')
1
# 是否支持腾讯视频 SDK 高清播放器
customBrowserInterface.supportVideoPlayer();
返回值:
"1": 支持
"0": 不支持
1
2
3
4
2
3
4
# 利用腾讯视频 SDK 高清播放器全屏播放
if (
'object' == typeof customBrowserInterface &&
'1' == customBrowserInterface.supportVideoPlayer()
) {
if ('0' == customBrowserInterface.fullScreenPlay(vid, title))
alert('不支持腾讯视频SDK高清播放器,请使用video标签播放')
} else alert('不支持腾讯视频SDK高清播放器,请使用video标签播放')
1
2
3
4
5
6
7
2
3
4
5
6
7
# 利用腾讯视频 SDK 高清播放器在指定位置播放
if (
'object' == typeof customBrowserInterface &&
'1' == customBrowserInterface.supportVideoPlayer()
) {
var offset = $('#videoImage').offset() /*封面图的绝对位置*/
if (
'0' ==
customBrowserInterface.customPlay(
vid,
title,
offset.left,
offset.top,
offset.width,
offset.height
)
)
alert('不支持腾讯视频SDK高清播放器,请使用video标签播放')
} else alert('不支持腾讯视频SDK高清播放器,请使用video标签播放')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 网页的尺寸发生变化时重新调整播放器的位置,可监听 onresize 事件,如:onresize="onresize()"
if (
'object' == typeof customBrowserInterface &&
'1' == customBrowserInterface.supportVideoPlayer()
) {
var offset = $('#videoImage').offset() /*封面图的绝对位置*/
customBrowserInterface.resizeCustomPlayer(
offset.left,
offset.top,
offset.width,
offset.height
)
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 销毁视频播放器
if (
'object' == typeof customBrowserInterface &&
'1' == customBrowserInterface.supportVideoPlayer()
) {
customBrowserInterface.hideVideoPlayer()
}
1
2
3
4
5
6
2
3
4
5
6
# 页面打开微信小程序
//id: 小程序id , path: 小程序对应页面路径
customBrowserInterface.openMiniProgram(id, path)
1
2
2