Categories
Android Java

Android: WebView and “date” input type

During the porting of an application from iPad to Android I found a problem within a webpage used to register a user on an external service. This page uses some html5 tags that are not compatible with some Android devices, in particular the “date” input tag.

The major problem is that I can’t modify the page but instead I have to do something to show the user a datepicker. Then I thought that I can use a jqueryui’s datepicker, after all I just need to inject a javascript call into this page and declare that this field needs to be initialized as a datepicker.

webView = (WebView) findViewById(R.id.webViewRegistration);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient(){

       @Override
        public void onPageFinished(WebView view, String url){
	        webView.loadUrl("javascript: $(\".form-date\").datepicker({ dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true yearRange: \"-100:-10\"}).datepicker(\"option\", $.datepicker.regional[ \"it\" ]);"
                                                 + "$(\".form-date\").val(\"1990-01-01\");"
                                                 + "$(\"#form-registrazione\").get(0).setAttribute('action', '" + Singleton.getInstance).getConfig().getUrlRegistration() + "');");
	}
});

new LoadPageTask().execute();

As you can see I just find the webview by it’s id, then I need to enable the javascript support and then declare a new WebViewClient in order to inject the javascript after the page is loaded. In order to leave the original scripts intact I choose this way, because as you can see below I need to reinclude the original scripts from the assets.

To load a javascript you can use the loadUrl method by using “javascript:” aht the beginning of the string. Like this: webView.loadUrl(“javascript:some_javascript_operations”);

The javascript operations are some simple jquery function that initializes a field with class “form-date” with a datepicker with some custom options. The last line will change the form’s action url, this is needed because normally that url contains a relative path to the server, but since the basepath will be inside the device it’s necessary to change the url with the fully qualified one retrieved from the APIs (the Singleton.getInstance().getConfig().getUrlRegistration() call to retrive the correct url).

Then the last thing to do is to launch a thread that will load the page into the webview. The thread is a pretty standard implementation of AsyncTask class with a progress bar and with an http connection.

private class LoadPageTask extends AsyncTask<Void, Void, Void>{

		private ProgressDialog progressDialog;

                String htmlcode = "";

		protected void onPreExecute(){
			//create a new progress dialog
			progressDialog = ProgressDialog.show(c, "", "Loading...", true);
		}

		protected Void doInBackground(Void... params) {

			Document doc;
	        try {
	            doc = Jsoup.connect(Singleton.getInstance().getRegistrationURL()).userAgent("Mozilla/5.0 Gecko/20100101 Firefox/21.0").get();

	            // remove all the css and js import from the documet
	            doc.head().getElementsByTag("link").remove();
	            doc.head().getElementsByTag("script").remove();
	            // add the new imports from the assets folder
	            doc.head().appendElement("link").attr("rel", "stylesheet").attr("type", "text/css").attr("href", "css/jquery-ui-1.10.3.custom.min.css");
	            doc.head().appendElement("link").attr("rel", "stylesheet").attr("type", "text/css").attr("href", "main.css");
	            doc.head().appendElement("script").attr("type", "text/javascript").attr("src", "jquery-1.9.1.js");
	            doc.head().appendElement("script").attr("type", "text/javascript").attr("src", "jquery-ui-1.10.3.custom.min.js");
	            doc.head().appendElement("script").attr("type", "text/javascript").attr("src", "common.js");
	            // convert the stream to html
	            htmlcode = doc.outerHtml();

	        } catch (IOException e) {
	            e.printStackTrace();
	        }

			return null;
		}

		protected void onPostExecute(Void result){
			//load the content into the webview using as basepath the folder that contains the scripts
			webView.loadDataWithBaseURL("file:///android_asset/registrazione/", htmlcode, "text/html", "UTF-8", null);
                        //then remove the progress dialog
			progressDialog.dismiss();
		}

	}

In order to remove the old imports from the document and then add the new ones, I used the jsoup library (http://jsoup.org/).

By croma25td

A post-degree computer science student actually in a internship with a web agency.