This answer will be from Android App Developer perspective.
I hope it will help someone.
The problem was very similar for me: I was opening a web site via webview, and some of the links were opening in a new window. The thing is that webview cannot work with web windows out of the box. I mean, it can be possible, but not as expected (in my case, when a link was opened in a separate window from javascript perspective, it were overriding previously opened page, and cannot be closed with a window.close()
from javascript, which eventually were causing a state loss on a previous page).
So the task in my case was to open a single link in a window and go back to previous page without any state loss. That was my solution.
I had two separate WebView
s - one as a main one, and one for links in window.
To be able to react on a "link in new window" event, I'll configured main webView with this code:
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
}
}
We need only onCreateWindow
callback to override in main webView chrome client, since it will only open new windows. And also allow a multiwindow support in webView.settings
. When an onCreateWindow
callback triggers, do the following:
@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()
}
}
Basically we're sending this (create window) request to a separate webView
. In it we should also allow a multiwindow support and attach a chrome client, in wich we should listen only onCloseWindow
event, since this webView should behave as a window. When onCloseWindow
triggers, we're just closing (hiding/removing) webView that should act as a window, and returning to the main one. Here isWebWindowOpened
method call just checks if the windowWebView
is not null and visible.
private fun handleCloseWebWindowRequest() {
if (!isWebWindowOpened()) return
container.removeView(windowWebView)
webView.visibility = View.VISIBLE
windowWebView = null
}
The only thing I can mention, is that when a windowWebView
is opened, onBackPressed
action should close it calling handleCloseWebWindowRequest
.