Tuesday, April 29, 2014

Understanding Android's WebChromeClient onCreateWindow Method

A complete demo application is on my GitHub account at:



Android's WebViews are pretty easy to use with the notable exception of the WebChromeClient's onCreateWindow. It is called when the webview would like the host application to create a new window. And new is the key. If you don't create a new webview, the call to onCreateWindow will fail, and worse yet, it will fail without exceptions or errors.

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.



Be sure to check out the complete source code on my GitHub account at the link at the top of the article.