Understanding Android's WebChromeClient onCreateWindow Method
A complete demo application is on my GitHub account at:

I initially had trouble with onCreateWindow. I couldn't seem to get it to work correctly and unfortunately I couldn't find a good working example of its use anywhere on the Internet. So I very carefully read the documentation again and follow the instructions to the letter. My first attempt to use onCreateWindow didn't create a new window, instead I tried to recycle a child webview that was already on the page. It didn't work, it didn't cause an error, and it did create an Intent for the web browser.
In order to get onCreateWindow to work, I created a special layout first. Take a look at main.xml. In it holds both the main webview and a relative layout, mainBrowserLayout, which will hold the child web view once it is created.
onCreateWindow is triggered whenever the user taps on an <a> tag with the target attribute is set to "_blank". In a browser this would cause the destination link to open in a new window or tab, but since we are in a webview, there is no way to do this without the help of the parent application, hence the called to onCreateWindow and its behavior of launching the browser if the call fails.
The heart of this application is off course the onCreateWindow method. The first thing it does is remove any current child windows which may still be attached to browserLayout. Then it makes the entire childLayout visible. It is by default set invisible. Next we create a new webview and give it some settings to make it function correctly. I added the new web to browserLayout. Then I do all of the required work to inform the new webview that it will be used to display the new link.
Next we set the webview client. I only implement this method so that I have access to the onPageFinished method. I use this method to read the title of the view, then set that text in mainTitleText TextView.
To inform the system that our newly create webview will be used for the link's page, we convert the resultMsg.obj into a WebViewTransport, then we call the setWebView with a reference to the new webview.
The last thing we do isn't necessary but makes things look cooler. We animate the childLayout sliding up from the bottom of the screen. The animation for it and its counterpart sliding down are in the anim folder.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Override | |
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) { | |
// remove any current child views | |
browserLayout.removeAllViews(); | |
// make the child web view's layout visible | |
childLayout.setVisibility(View.VISIBLE); | |
// now create a new web view | |
WebView newView = new WebView(myActivity); | |
WebSettings settings = newView.getSettings(); | |
settings.setJavaScriptEnabled(true); | |
settings.setJavaScriptCanOpenWindowsAutomatically(true); | |
settings.setSupportMultipleWindows(true); | |
settings.setUseWideViewPort(false); | |
newView.setWebViewClient(new WebViewClient() { | |
/** | |
* Need to grab the title of the web page | |
* @param view - - the web view | |
* @param url - the URL of the page | |
*/ | |
public void onPageFinished(WebView view, String url) { | |
// once the view has loaded, display its title | |
titleText.setText(view.getTitle()); | |
} | |
}); | |
// add the new web view to the layout | |
newView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); | |
browserLayout.addView(newView); | |
// tell the transport about the new view | |
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; | |
transport.setWebView(newView); | |
resultMsg.sendToTarget(); | |
// let's be cool and slide the new web view up into view | |
Animation slideUp = AnimationUtils.loadAnimation(myActivity, R.anim.slide_up); | |
childLayout.startAnimation(slideUp); | |
return true; | |
} |
Be sure to check out the complete source code on my GitHub account at the link at the top of the article.