Android Webview:脚本可能只关闭由它打开的窗口

G B*_*G B 3 android webview

我正在加载特定的网址

例如。

webview.loadUrl("some.domain.com")
Run Code Online (Sandbox Code Playgroud)

余言之后,我将其重定向到其他域,然后返回到我的域。然后,我尝试在我的JavaScript(window.close())中关闭窗口。在chrome开发人员工具上进行远程调试时,出现以下错误

脚本只能关闭它打开的窗口。

即使我在打开它的同一个域中,也遇到了以上错误。

任何帮助将不胜感激。谢谢。

Dem*_*god 5

这个答案将从Android App Developer的角度来看。希望对您有所帮助。

对我来说,问题非常相似:我正在通过webview打开一个网站,并且某些链接在新窗口中打开。问题是webview不能与Web窗口一起使用。我的意思是,这是可能的,但是却没有达到预期的效果(就我而言,当从javascript角度在单独的窗口中打开链接时,它覆盖了以前打开的页面,并且无法使用window.close()from javascript 来关闭它,这最终导致了前一页的状态丢失)。

因此,在我的案例中,任务是在窗口中打开单个链接,然后返回上一页而不会造成任何状态损失。那是我的解决方案。我有两个单独的WebViews-一个作为主要的,另一个用于窗口中的链接。为了能够对“新窗口中的链接”事件做出反应,我将使用以下代码配置主webView:

    webView.settings.javaScriptEnabled = true
    webView.settings.javaScriptCanOpenWindowsAutomatically = true
    webView.settings.setSupportMultipleWindows(true)

    webView.webChromeClient = object : WebChromeClient() {

    override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean,
                                resultMsg: Message?): Boolean {
        handleCreateWebWindowRequest(resultMsg)
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

我们只需要onCreateWindow在主webView chrome客户端中覆盖回调即可,因为它只会打开新窗口。并且还允许在中提供多窗口支持webView.settings。当onCreateWindow回调触发时,请执行以下操作:

@SuppressLint("SetJavaScriptEnabled")
override fun handleCreateWebWindowRequest(resultMsg: Message?) {
    if (resultMsg == null) return
    if (resultMsg.obj != null && resultMsg.obj is WebView.WebViewTransport) 
        {
        val transport = resultMsg.obj as WebView.WebViewTransport
        windowWebView = WebView(this)
        windowWebView?.layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, 
        ViewGroup.LayoutParams.MATCH_PARENT)

        windowWebView?.settings?.javaScriptEnabled = true
        windowWebView?.settings?.javaScriptCanOpenWindowsAutomatically = true
        windowWebView?.settings?.setSupportMultipleWindows(true)
        windowWebView?.webViewClient = WebViewClient()
        windowWebView?.webChromeClient = object : WebChromeClient() {
            override fun onCloseWindow(window: WebView?) {
                super.onCloseWindow(window)
                handleCloseWebWindowRequest()
            }
        }

        container.addView(windowWebView)
        webView.visibility = View.GONE
        transport.webView = windowWebView
        resultMsg.sendToTarget()
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,我们将此请求(创建窗口)发送到单独的webView。在其中,我们还应该允许多窗口支持并附加chrome客户端,因此我们应该只侦听onCloseWindow事件,因为此webView应该充当窗口。当onCloseWindow触发时,我们只是关闭(隐藏/删除)应该作为窗口的webView,然后返回到主窗口。这里的isWebWindowOpened方法调用只是检查,如果windowWebView不为null且不可见。

private fun handleCloseWebWindowRequest() {
    if (!isWebWindowOpened()) return

    container.removeView(windowWebView)
    webView.visibility = View.VISIBLE
    windowWebView = null
}
Run Code Online (Sandbox Code Playgroud)

我唯一能提到的是,当windowWebView打开a时,onBackPressed动作应关闭它并调用handleCloseWebWindowRequest