如题,组内一位同事最近想用原生Android 的Webview加载 Vue 应用,替代原来的 RN react-native-webview 组件的使用
然后遇到如下异常问题,界面上看到是网络是OK的,页面也加载到了(显示出了标题),但页面内容主体没有正常显示出来
如下是 chrome inspect 到手机应用的webview页面看到的界面
chrome://inspect/#devices
由于是连着服务器上的页面,具体的代码行数是看不到的!
分析
因为我也有 vue应用的项目代码,那么我们可以本地启动 vue项目 ,然后 Webview 加载的远程页面,改为加载本地电脑上启动的 Vue应用,然后加载对应 H5 页面即可
先启动 vue 应用
然后手机应用的 Webview 加载本地页面(之前远程 url的域名替换为本地的ip与端口,页面后面的path 与其它参数保持不变)
最后可以看到并找到触发异常的具体代码了,nice
点击栈顶的行,就跳转到了具体的源码了!
如上所示,就是 vue页面在onMounted 生命周期函数中调用 localStorage 的 setItem,然后该方法为 null,就抛异常了,导致后面的逻辑没有执行到,所以页面的主体内容没有显示出来。
localStorage 是浏览器标准 API,为什么 setItem会为空呢?
这个就得跟 Android Webview 的组件的功能配置有关了呀!(Android 下默认 WebView 的很多功能是没有开启的,需要我们一个个手动开启)
这里的 case 主要跟DOM storage API的权限配置有关,具体是如下接口说明(DOM storage API默认是关闭的)
/**
* Sets whether the DOM storage API is enabled. The default value is {@code false}.
*
* @param flag {@code true} if the WebView should use the DOM storage API
*/
public abstract void setDomStorageEnabled(boolean flag);
解决
大概的 webview配置如下:,最关键是 domStorageEnabled为true
PS:如下是 Kotlin 代码
private fun initWebView() {
val webView: WebView = binding.webView
val webSettings: WebSettings = webView.settings
webSettings.javaScriptEnabled = true // 允许JavaScript执行
webSettings.domStorageEnabled = true // 允许DOM存储
webSettings.allowFileAccess = true // 允许访问文件
webView.webViewClient = WebViewClient() // 设置WebViewClient以处理页面加载完成事件
// todo 扩展WebViewClient子类,于监听更多的网面加载事件,如onPageStarted, onPageFinished 等
webView.loadUrl("https://www.baidu.com") // 加载百度首页
」