WebView不会在外部URL上启动新选项卡。

huangapple go评论54阅读模式
英文:

WebView not launching new tab with external URL

问题

I can provide a translation of the code section you provided:

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

webView.addView(newWebView)

webView.webChromeClient = object : WebChromeClient() {
   
    override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message?): Boolean {
        val newWebView = WebView(requireActivity())
        newWebView.settings.setSupportZoom(true)
        newWebView.settings.loadWithOverviewMode = true
        newWebView.settings.javaScriptEnabled = true
        newWebView.settings.offscreenPreRaster = true
        newWebView.settings.setSupportMultipleWindows(true)
        newWebView.settings.javaScriptCanOpenWindowsAutomatically = true

        newWebView.webViewClient = object : WebViewClient() {
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                // Starts loading
                super.onPageStarted(view, url, favicon)
            }

            override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                // Never called
                val newUrl = request?.url?.toString()
                val browserIntent = Intent(Intent.ACTION_VIEW)
                browserIntent.data = Uri.parse(newUrl)
                startActivity(browserIntent)
                return true
            }

            override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
                // Never called
                handler?.proceed()
            }
        }

        val transport = resultMsg?.obj as? WebView.WebViewTransport
        transport?.webView = newWebView
        resultMsg?.sendToTarget()

        return true
    }
}

Please note that the code you provided is written in Kotlin and is related to WebView configuration. If you need further assistance or have specific questions about this code, feel free to ask.

英文:

I'm running into an issue where entering a bank account triggers an Authenticate pop-up for users inside a WebView. This pop-up is controlled via Stripe.js. Currently, the "Auth" button is shown but nothing happens when the user clicks on it. I can see that the onPageStarted is triggered via the WebViewClient with the url. The user receives an OTP via SMS, but because nothing happens they have nowhere to enter it.

On Chrome, the Auth button opens a new tab where it loads a page for the user to enter the OTP. Why is this new page not loading given the code below? Am I adding the new WebView correctly? I don't see any documentation on this. This is the only example I've found https://stackoverflow.com/a/27010225/1649472

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

    webView.addView(newWebView)

    webView.webChromeClient = object : WebChromeClient() {
       
        override fun onCreateWindow(view: WebView?, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message?): Boolean {
            val newWebView = WebView(requireActivity())
            newWebView.settings.setSupportZoom(true)
            newWebView.settings.loadWithOverviewMode = true
            newWebView.settings.javaScriptEnabled = true
            newWebView.settings.offscreenPreRaster = true
            newWebView.settings.setSupportMultipleWindows(true)
            newWebView.settings.javaScriptCanOpenWindowsAutomatically = true

            newWebView.webViewClient = object : WebViewClient() {
                override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                    // Starts loading
                    super.onPageStarted(view, url, favicon)
                }

                override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                    // Never called
                    val newUrl = request?.url?.toString()
                    val browserIntent = Intent(Intent.ACTION_VIEW)
                    browserIntent.data = Uri.parse(newUrl)
                    startActivity(browserIntent)
                    return true
                }

                override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
                    // Never called
                    handler?.proceed()
                }

            }

            val transport = resultMsg?.obj as? WebView.WebViewTransport
            transport?.webView = newWebView
            resultMsg?.sendToTarget()

            return true
        }
    }

答案1

得分: 1

Inside onCreateWindow you have handle where to display the new childWebview. resultMsg and WebViewTransport is to actually connect the separate webview into one window relationship. To note that, adding view to webView is unsupported, so you have to display the webview elsewhere. For example, by adding a new webView to the LinearLayout that wraps the entire fragmentView.

To summarize the comment and example, below is a minimum functional example of opening a new window:

class WebExampleFragment: Fragment() {

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ) = WebView(inflater.context).apply {
        viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver{ _, event ->
            when (event) {
                Lifecycle.Event.ON_PAUSE -> onPause()
                Lifecycle.Event.ON_RESUME -> onResume()
                Lifecycle.Event.ON_DESTROY -> destroy()

                else -> {}
            }
        })
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val webView = view as WebView
        webView.settings.javaScriptEnabled = true
        webView.settings.domStorageEnabled = true
        webView.settings.javaScriptCanOpenWindowsAutomatically = true
        webView.settings.setSupportMultipleWindows(true)
        webView.webViewClient = WebViewClientCompat()
        webView.webChromeClient = object: WebChromeClient() {

            override fun onCreateWindow(view: WebView, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message): Boolean {
                val transport = resultMsg.obj as WebViewTransport
                val childWebView = WebView(view.context)
                childWebView.settings.useWideViewPort = true
                childWebView.webViewClient = WebViewClientCompat()
                val dialog = MaterialAlertDialogBuilder(view.context)
                        .setView(childWebView).create()
                transport.webView = childWebView
                childWebView.webChromeClient = object: WebChromeClient() {

                    override fun onCloseWindow(window: WebView) {
                        if (window === childWebView) {
                            dialog.dismiss()
                        }
                    }

                }
                resultMsg.sendToTarget()
                dialog.show()
                return true
            }

        }
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.withResumed {
                webView.evaluateJavascript("""
            window.open("https://www.google.com");
        """.trimIndent(), null)
            }
        }

    }
}

[![enter image description here][1]][1]


[![enter image description here][1]][1]

<details>
<summary>英文:</summary>

Inside `onCreateWindow` you have handle where to display the new childWebview. `resultMsg` and `WebViewTransport` is to actually connect the separate webview into one window relation ship. 
To note that, adding view to webView is unsupported. so you have display the webview else where. For example, adding new webView to the `LinearLayout` that is wrapping the whole fragmentView.


To summarize the comment and example. Below is minimum functional example of opening new window.


class WebExampleFragment: Fragment() {

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
) = WebView(inflater.context).apply {
    viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver{ _, event -&gt;
        when (event) {
            Lifecycle.Event.ON_PAUSE -&gt; onPause()
            Lifecycle.Event.ON_RESUME -&gt; onResume()
            Lifecycle.Event.ON_DESTROY -&gt; destroy()

            else -&gt; {}
        }
    })
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val webView = view as WebView
    webView.settings.javaScriptEnabled = true
    webView.settings.domStorageEnabled = true
    webView.settings.javaScriptCanOpenWindowsAutomatically = true
    webView.settings.setSupportMultipleWindows(true)
    webView.webViewClient = WebViewClientCompat()
    webView.webChromeClient = object: WebChromeClient() {

        override fun onCreateWindow(view: WebView, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message): Boolean {
            val transport = resultMsg.obj as WebViewTransport
            val childWebView = WebView(view.context)
            childWebView.settings.useWideViewPort = true
            childWebView.webViewClient = WebViewClientCompat()
            val dialog = MaterialAlertDialogBuilder(view.context)
                    .setView(childWebView).create()
            transport.webView = childWebView
            childWebView.webChromeClient = object: WebChromeClient() {

                override fun onCloseWindow(window: WebView) {
                    if (window === childWebView) {
                        dialog.dismiss()
                    }
                }

            }
            resultMsg.sendToTarget()
            dialog.show()
            return true
        }

    }
    viewLifecycleOwner.lifecycleScope.launch {
        viewLifecycleOwner.withResumed {
            webView.evaluateJavascript(&quot;&quot;&quot;
        window.open(&quot;https://www.google.com&quot;);
    &quot;&quot;&quot;.trimIndent(), null)
        }
    }

}

}


[![enter image description here][1]][1]


  [1]: https://i.stack.imgur.com/qEOI1.png

</details>



huangapple
  • 本文由 发表于 2023年4月11日 00:50:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75978990.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定