I've been digging in Android sources for days searching for the cause for this, I've even offered a bounty for 100 points which no one claimed.
I've seen many similar issues such as this, across StackOverFlow...
The main issue is that the loading of the page is completed, and then the onPageFinished event is called with a seemly random delay that can range from 0.1 - 40 sec, only after the <GATE-M>DEV_ACTION_COMPLETED</GATE-M> is printed to the log.
Here is the code snippet:
webView = (WebView) view.findViewById(R.id.WebView); webView.setWebViewClient(new WebViewClient() { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { logDebug("Loading URL: " + url); super.onPageStarted(view, url, favicon); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { return WrappingClass.this.shouldOverrideUrlLoading(view, url); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); logInfo("Injecting JavaScript to webview."); webView.loadUrl("full-js-here"); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { logError("error code:" + errorCode); super.onReceivedError(view, errorCode, description, failingUrl); } }); WebSettings webSettings = webView.getSettings(); webSettings.setSavePassword(false); webSettings.setSaveFormData(false); webSettings.setJavaScriptEnabled(true); webView.requestFocus(View.FOCUS_DOWN); webView.loadUrl("url");
So the solution is quite a hack but it is wonderful... Check it out:
Somewhere in your class declare the following:
final class ObjectExtension {@JavascriptInterface
public void onLoad() { logInfo("onLoadCompleted"); WrappingClass.this.onLoadCompleted(); } }
public void onLoadCompleted() { webView.loadUrl("full-js-here"); }
And before the URL loading add the following:
webView.addJavascriptInterface(new ObjectExtension(), "webviewScriptAPI"); String fulljs = "javascript:(\n function() { \n"; fulljs += " window.onload = function() {\n"; fulljs += " webviewScriptAPI.onLoad();\n"; fulljs += " };\n"; fulljs += " })()\n"; webView.loadUrl(fulljs);
webView.loadUrl("url");
This registers a callback for the onLoad event of the WebView window, which is loaded long time before the onPageFinished is called, because of that Android WebView issue.
So the trick is that we inject the onLoad callback before loading the url, later (next line) we load the url, once the onLoad callback is called, in our onLoad implementation we call to the Java API, which in its turn inject the Javascript into the loaded page, and sometime long after that the onPageFinished is called.
End of story...
---- UPDATE ----
It has been a very long while since that post... I've wrote SocialApp(link at the top Left), which is entirely a WebView application, a multi WebView applications, which runs Javascripts on all of the WebViews and monitor the beginning and ends of scripts, and runs Javascript on a WebViews in the background....
What I'm trying to say is, if you have any questions, I'm pretty sure I can answer them, so ask away...
---- UPDATE ----
It has been a very long while since I posted that update, I really hoped to release it as an open source, and was struggling with it for a long time, but as it was pretty much forced on me due to the architecture I've been decided to append this "CyborgWebView" to Cyborg, which is a license based SDK, You can find it here.
Also, if the post is not clear enough, and you prefer a sample project, let me know...