I have a WebView in my app that displays a page not belonging to me. My desired behavior is, if any link is tapped by the user, the device's Browser app is launched, and the resulting page is loaded there. Unfortunately, this page is doing some weird things, so shouldOverrideUrlLoading()
does not fire.
My attempted solution is to hook some javascript into pushState and use an interface to run Android code to launch the browser app.
Here is my interface:
public class LaunchExternalBrowserHack {
Context mContext;
LaunchExternalBrowserHack(Context c) {
mContext = c;
}
@JavascriptInterface
public void launchExternalBrowser(String url) {
openUrl(url);
}
}
I'm injecting some javascript into the page in onPageFinished()
:
public void onPageFinished(WebView view, String url) {
mWebView.loadUrl(javascript);
}
Here is my javascript:
private final String javascript = "javascript:history.pushState = function (state, title, url) { console.log(url); console.log(location.href); Uphoria.launchExternalBrowser(location.origin, url); };";
And, of course, I'm adding the interface to the WebView
:
mWebView.addJavascriptInterface(new LaunchExternalBrowserHack(getContext()), "Android");
So this seems to work. The Browser app is launching and the next page is opening.
However, the WebView is also moving forward, too. I want to prevent this, but I cannot find a way to prevent the WebView moving forward while still allowing me to capture the forwarding url and launch the Browser app. As I mentioned earlier, with this webpage, shouldOverrideUrlLoading
is not firing.
Ideas?
The user is trying to move away from the page. to stop him from moving out, return false. to let him move away, don't return anything but you can execute any code that you may want. This event is fired immediately when navigation event occurs including page refresh.
private final String javascript = "window.onbeforeunload = function(){ dosomething(); }; window.unload = function(){ dosomething(); }; function dosomething() { /* Write code here */ };"
You need to include the entire javascript code above, since some browsers use onbeforeunload
and some use unload
EDIT
After careful reading of your problem I found my solution to be of little use.
Here's another approach using history
. If your history is blank, that means its the first page. but if you have some items in history, it means that navigation has occurred.
You can check it as following
private final String javascript = "javascript:"+"if(window.history.length>=1 && document.referrer=='') Android.launchExternalBrowser(location.href);";
This answer is wrong. Kept here because it has importantly relevant comments.
The reason that you are not getting a result from your Javascript, is that you are not calling a function directly. You are assigning a function in your Javascript that returns a value, but it will not return that to your code, it will return that to whatever calls history.pushState()
.
private final String javascript = "javascript:" + "var pushState = history.pushState; history.pushState = function () " +
"{ pushState.apply(history, arguments); console.log(arguments); return location.href; " +
"};";
Instead, you can test whether something like this returns you a value:
private final String javascript = "(function() { return location.href; })();";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With