前段时间公司要求写个游戏嵌入到 App 中,我们通过
webview
链接到 App 中,中间遇到了很多坑,在此记录一下。
1 | const sourceAndroid = { uri: 'file:///android_asset/trivia-game/index.html' }; |
官方介绍: webview,其中像 javaScriptEnabled
这些属性是我们常用的,还有一些不常用但很能填坑的属性下面介绍下
webview 与 react-native 通信
目前只能传递字符串
webview
给 react-native
发消息:
1 | window.postMessage('str') |
react-native
通过 onMessage
接受消息:
1 | _onMessage = (e) => { |
react-native
给 webview
发消息:
1 | this.webView.postMessage('str'); |
webview
接受消息:
1 | document.addEventListener( 'message', event => { |
自动计算 webview 高度
刚开始我使用的是
onLoadEnd
计算网页高度。当图片加载成功时 Android 和 Ios 都 OK 。如果有图片加载失败, Ios Ok , Android 的高度会计算失败,内容显示不全。
1
2
3
4
5
6
7
8
9
10 _onLoadEnd = () => {
const script = `window.postMessage(document.body.scrollHeight)`;
this.webView.injectJavaScript(script);
};
_onMessage = (event) => {
const height = parseInt(event.nativeEvent.data) || 0;
if (height > 0) {
this.setState({ webViewHeight: height });
}
};
下面的方案可以修复上面的问题:
在 index.html
中添加:
1 | <head> |
在 react-native
监听 onNavigationStateChange
:
1 | _onNavigationStateChange = (navState) => { |
打包后 react-native 找不到资源
我们的 index.html
引用了其他的 js , 而 js 中引用了很多图片、音乐、字体 …
Android 和 Ios 中需要放在各自的资源目录下,具体是:
- Android :
android/app/src/main/assets/
下,将游戏打包后的文件夹trivia-game
放到前面的目录下。webview
中source
对应的地址为file:///android_asset/trivia-game/index.html
。webview
必须添加allowUniversalAccessFromFileURLs={ true }
,不然只能读到 js ,而不能读取到 js 引用的其他资源。
这是这个属性的介绍: Boolean that sets whether JavaScript running in the context of a file scheme URL should be allowed to access content from any origin. Including accessing content from other file scheme URLs - Ios :
ios/external/
下,若没有 external 目录则先新建一个, 将游戏打包后的文件夹trivia-game
放到前面的目录下。webview
中source
对应的地址为./trivia-game/index.html
。
另外,Android 下的 Webview
不识别 svg
文件 ,我目前的做法是将文件转为了 base64
格式,不知道有大佬有更好的方案吗?
ios 下 音乐不自动播放
添加属性: mediaPlaybackRequiresUserAction={ false }
, 原因是 Ios 默认需要用户操作才可以播放音乐和视频
调试工具
- Android :
chrome://inspect/#devices 是很好用的工具,之前调试webview
、手机网页 都很好用。但在 genymotion 模拟器中,整个调试器的样式都是乱的。查询到这个 答案, 原因是 Chrome 去掉了一个api
,所以我下了旧版的 Chromium。前面答案的超链接里有下载地址。 - Ios : 使用 Safari ,具体参考 这儿