代码之家  ›  专栏  ›  技术社区  ›  Binary Baba

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

  •  5
  • Binary Baba  · 技术社区  · 7 年前

    我正在加载特定的url

    对于eg。

    webview.loadUrl("some.domain.com")
    

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

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

    我得到了上述错误,即使我在同一个域,我打开了它。

    任何帮助都将不胜感激。非常感谢。

    1 回复  |  直到 7 年前
        1
  •  10
  •   Demigod    7 年前

    这个答案将从Android应用程序开发人员的角度给出。 我希望它能帮助别人。

    问题对我来说非常相似:我正在通过webview打开一个网站,其中一些链接正在一个新窗口中打开。问题是webview无法使用现成的web窗口。我的意思是,这是可能的,但并不像预期的那样(在我的情况下,当从javascript角度在单独的窗口中打开链接时,它会覆盖以前打开的页面,并且不能用 window.close() 来自javascript,最终导致前一页上的状态丢失)。

    因此,在我的例子中,任务是在窗口中打开一个链接并返回上一页,而不丢失任何状态。这就是我的解决方案。 我有两个单独的 WebView 一个作为主链接,一个用于窗口中的链接。 为了能够对“新窗口中的链接”事件做出反应,我将使用以下代码配置主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
        }
    }
    

    我们只需要 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()
        }
    }
    

    基本上,我们将此(创建窗口)请求发送到单独的 webView . 在它中,我们还应该允许多窗口支持并连接一个chrome客户端,在这个客户端中,我们应该只监听 onCloseWindow 事件,因为此webView应作为窗口。什么时候 onCloseWindow窗口 触发器,我们只是关闭(隐藏/删除)应该作为窗口的webView,然后返回到主视图。在这里 isWebWindowOpened 方法调用只检查 windowWebView 不为null且不可见。

    private fun handleCloseWebWindowRequest() {
        if (!isWebWindowOpened()) return
    
        container.removeView(windowWebView)
        webView.visibility = View.VISIBLE
        windowWebView = null
    }
    

    我唯一能提到的是 windowWebView 已打开, onBackPressed 操作应关闭调用 handleCloseWebWindowRequest .