WebView - opening a new window

I was previously using PhoneGap for an app of mine. I wasn’t using any of the device features really, but I used PhoneGap because that’s all I knew how to do in 2011.

Anyway, suddenly there are problems with the version of PhoneGap I’m using on Android, so rather than try to fix it, I decided to use a Corona WebView.

It worked great!!!

Except, anywhere I’ve got an anchor tag like this (just an example):

<a href=“http://google.com” target="_blank">go to google in new window</a>

It won’t open a new window; it just opens inside the in-app webview as if that target="_blank" wasn’t even there.  It’s really disruptive to the app.  Is there any way to accomplish this?

I’m open even to intercepting the request, if that’s possible, and doing a native.showWebPopup or something, although it’d be much better if there’s some way to make those links actually open the native web browser on the device instead of inside the webview.

Thanks,

Dave

There should be an event listener that gets called when links are tapped.  You could intercept it and use system.openURL() to open it in the browser or another webview.

Rob

That sounds perfect, but it doesn’t work for me.  It still loads the page in the in-app webview, in addition to opening a new window.  I’ve included my code below.

main.lua:

local webView local function webListener( event ) if event.url then -- Open external links (http://) in a new window in the device browser. -- Open internal links (file://) normally. if (string.find(event.url, "http://", 1, true) ~= nil) then system.openURL(event.url) -- open links in new window return true -- stop event propagation? it doesn't seem to do so end end if event.errorCode then native.showAlert( "Error!", event.errorMessage, { "OK" } ) end end webView = native.newWebView( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) webView:addEventListener( "urlRequest", webListener ) webView:request( "index.html", system.ResourceDirectory ) local function onKeyEvent( event ) -- If the "back" key was pressed on Android, then prevent it from backing out of your app. if ((event.keyName == "back") and event.phase == "up") then webView:request( "index.html", system.ResourceDirectory ) return true end -- Return false to indicate that this app is \*not\* overriding the received key. -- This lets the operating system execute its default handling of this key. return false end Runtime:addEventListener( "key", onKeyEvent )

For reference, this is how I’ve resolved this problem…

local webView local function webListener( event ) if event.url then -- Open external links (http://) in a new window in the device browser. -- Open internal links (file://) normally. local index = string.find(event.url, "#http", 1, true) if (index ~= nil) then system.openURL(string.sub(event.url, index+1)) -- open links in new window; removing # at first char return true end end if event.errorCode then native.showAlert( "Error!", event.errorMessage, { "OK" } ) end end webView = native.newWebView( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) webView:addEventListener( "urlRequest", webListener ) webView:request( "index.html", system.ResourceDirectory )

In my html, those links to external sites have to be prefixed with a  #, like so:

\<a target="\_blank" href="#http://bit.ly/3RNgsc"\>http://bit.ly/3RNgsc\</a\>

It’s the only way I could prevent the webView from trying to load the requested URL.  

From my experiments with the webView on Android:

  • target="_blank" does not open a new window

  • window.open does not open a new window

  • there’s no way to stop the webView from loading a url; apparently by the time it gets into the webView’s event handler, it’s too late, or the return true just has no effect.

In figuring this out, I found that you can pass messages over to Corona from javascript this way.  Just do a window.open("#id-some data"), then in the request listener you can check for the “#id” where id is some identifier you make up, then grab everything after the dash as the data. There might be other ways to do it, but I haven’t seen a whole lot of info on it.

Dave

As an add-on to the bit about passing stuff from Javascript to Lua, you can also do it the other way around like this:

webView:request( "javascript:doSomething();" )

There should be an event listener that gets called when links are tapped.  You could intercept it and use system.openURL() to open it in the browser or another webview.

Rob

That sounds perfect, but it doesn’t work for me.  It still loads the page in the in-app webview, in addition to opening a new window.  I’ve included my code below.

main.lua:

local webView local function webListener( event ) if event.url then -- Open external links (http://) in a new window in the device browser. -- Open internal links (file://) normally. if (string.find(event.url, "http://", 1, true) ~= nil) then system.openURL(event.url) -- open links in new window return true -- stop event propagation? it doesn't seem to do so end end if event.errorCode then native.showAlert( "Error!", event.errorMessage, { "OK" } ) end end webView = native.newWebView( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) webView:addEventListener( "urlRequest", webListener ) webView:request( "index.html", system.ResourceDirectory ) local function onKeyEvent( event ) -- If the "back" key was pressed on Android, then prevent it from backing out of your app. if ((event.keyName == "back") and event.phase == "up") then webView:request( "index.html", system.ResourceDirectory ) return true end -- Return false to indicate that this app is \*not\* overriding the received key. -- This lets the operating system execute its default handling of this key. return false end Runtime:addEventListener( "key", onKeyEvent )

For reference, this is how I’ve resolved this problem…

local webView local function webListener( event ) if event.url then -- Open external links (http://) in a new window in the device browser. -- Open internal links (file://) normally. local index = string.find(event.url, "#http", 1, true) if (index ~= nil) then system.openURL(string.sub(event.url, index+1)) -- open links in new window; removing # at first char return true end end if event.errorCode then native.showAlert( "Error!", event.errorMessage, { "OK" } ) end end webView = native.newWebView( display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight ) webView:addEventListener( "urlRequest", webListener ) webView:request( "index.html", system.ResourceDirectory )

In my html, those links to external sites have to be prefixed with a  #, like so:

\<a target="\_blank" href="#http://bit.ly/3RNgsc"\>http://bit.ly/3RNgsc\</a\>

It’s the only way I could prevent the webView from trying to load the requested URL.  

From my experiments with the webView on Android:

  • target="_blank" does not open a new window

  • window.open does not open a new window

  • there’s no way to stop the webView from loading a url; apparently by the time it gets into the webView’s event handler, it’s too late, or the return true just has no effect.

In figuring this out, I found that you can pass messages over to Corona from javascript this way.  Just do a window.open("#id-some data"), then in the request listener you can check for the “#id” where id is some identifier you make up, then grab everything after the dash as the data. There might be other ways to do it, but I haven’t seen a whole lot of info on it.

Dave

As an add-on to the bit about passing stuff from Javascript to Lua, you can also do it the other way around like this:

webView:request( "javascript:doSomething();" )