I'm building an Android app as a mobile client for a website that does not (and will not) have it's own UI for mobile browsers. My chosen architecture uses a hidden WebView which I initialise (loadURL) with the login page, and then I load JavaScript to populate the login pages (there are two) with the user's name, password and other credentials. Once logged in, I'll navigate to a new URL and then use a JavaScriptInterface to extract sections of HTML from the pages for parsing and use in my app, following the tutorial here: http://lexandera.com/2009/01/extracting-html-from-a-webview/
My Webview has a JavaScriptInterface class with 3 methods:
class MyJavaScriptInterface {
@JavascriptInterface
public void method1(String html) { // do something }
@JavascriptInterface
public void method2(String html) { // do something }
@JavascriptInterface
public void method3(String html) { // do something }
}
and
WebSettings ws = getSettings();
ws.setSaveFormData(false);
ws.setJavaScriptEnabled(true);
addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
This scripting of the website is done in my WebView's WebViewClient.onPageFinished method, which checks the current URL and then executes the next step in the login/browsing process. i.e.
setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
String javascript;
if (url.contentEquals(<first login page>) {
javascript = "javascript:document.forms['aspnetForm'].elements[<my element>].value = <email address>;";
javascript += "document.getElementById(<id of Submit button>).click();";
view.loadUrl(javascript);
}
if (url.contentEquals(<second login page>) {
view.loadUrl(<javascript to enter further credentials and click Submit>);
}
if url.contentEquals(<welcome page>) {
view.loadUrl(<javascript to call JavaScriptInterface method1 with selected HTML>);
view.loadUrl(<javascript to call JavaScriptInterface method2 with selected HTML>);
view.loadUrl(<another page>);
}
if (url.contentEquals(<another page>) {
view.loadUrl(<javascript to call JavaScriptInterface method3 with selected HTML>);
}
}
My problem is that when running the app, the onPageFinished callback doesn't always get called for every page, so the process stalls. But when I debug in Eclipse/ADT, and single-step through the code, it seems to work perfectly every time and all the page navigation works and the JavascriptInterface methods get called.
Is there some thread or race condition issue to be considered here? Is there a better -more reliable and/or easier - way to architect this?