Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Exchanging Array Data between Java and JavaScript

Author: Ian Darwin
Published? false
FormatLanguage: WikiFormat

Problem:

You want to push array data from Java to JavaScript and/or from JavaScript to Java

Solution:

Simple set/get methods work for passing single values - a single integer, a single double - from Java to JavaScript or vice versa, as illustrated in 3547. However, for technical reasons, you cannot pass an array in either direction, so you have to convert it to JSON, and have get/set methods that deal in JSON Strings. Then you need to parse it: in JavaScript, use JSON.parse() and in Java use any of a dozen or so JSON packages, including the built-in (but slightly behind its origin) org.json parser.

Discussion:

This example shows a JavaScript example with two function, one that pulls an array of data from the Java code and the other that pushes a different array into the Java code.

To run the demo, press the Show button, then the Set button, then the Show button again; this time the new values will be in effect.

The file assets/jsdatademo.html follows. It has the usual "script" in the "head" element which defines some JavaScript functions, showData and setData. The first gets a JSON string from the Java code containing the array data, converts it to an array using JSON.parse, and then displays it, first using toString() implicitly and then extracting the first element to prove that it is being treated as an array.

The setData() function of course goes in the opposite direction.

And at the bottom are two Button elements to invoke the two functions.

<script> 
        var showData = function() {
            var data = android.getData(); data = JSON.parse(data);
            window.alert("Hello! Data are: " + data + "; first = " + data[0]);
        }
        var setData = function() {
        	android.setData('[10,20,30]');
        	window.alert("Data have been updated; press 'Display' again to prove it.");
        }
</script>
</head>

<body>
<input type="button" value="Display data" onclick="showData()">
<input type="button" value="Update data" onclick="setData();">

The Java code is all in the main activity. The onCreate() method has to do a bit of setup for the WebView, including enabling JavaScript (which now gives a warning about cross-site scripting, which I turn off here but you should be more careful in a real app!).

One key part of onCreate is the call <kbd>addJavascriptInterface(this, "android");</kbd> which creates an entry in the JavaScript namespace under the imaginative name "android". This will contain all the public methods that are annotated with @JavaScriptInterface (in Android 2.x this was not needed; all public methods would be exposed). You could use an inner class, but since the annotation limits the exposure to methods sporting it, there's no real need in this simple demo; your mileage may vary in a real app.

	@SuppressLint("SetJavaScriptEnabled")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		WebView webView = (WebView) this.findViewById(R.id.webView);
		WebSettings webSettings = webView.getSettings();
		webSettings.setJavaScriptEnabled(true);
		webView.addJavascriptInterface(this, "android");
		webView.requestFocusFromTouch();
		webView.setWebViewClient(new WebViewClient());
		webView.setWebChromeClient(new WebChromeClient());
		webView.loadUrl("file:///android_asset/jsdatademo.html");
	}

Then we have the data, an array of doubles. and the set and get methods for it. These are responsible for doing JSON conversion.

	
	double[] data = new double[] {42.6, 24, 17, 15.4};
	
	/** This passes our data out to the JS */
	@JavascriptInterface
	public String getData() {
		Log.d(TAG, "getData() called");
		return a1dToJson(data).toString();
	}
	
	/** Allow the JavaScript to pass some data in to us. */
	@JavascriptInterface
	public void setData(String newData) throws JSONException {
		Log.d(TAG, "MainActivity.setData()");
		JSONArray streamer = new JSONArray(newData);
		data = new double[streamer.length()];
		for (int i = 0; i < streamer.length(); i++) {
			Double n = streamer.getDouble(i);
			data[i] = n;
		}
	}

In one case I hand-rolled the JSON and in the other I use Android's built-in JSON support. Sorry for not using the standard org.json.JSONArray in getData(), but even in Android 4.2 it lacks the JSONArray(Object[]) constructor, making it too painful to use.

Download:

The source code for this project is in the Android Cookbook repository, http://github.com/IanDarwin/Android-Cookbook-Examples/,in the subdirectory JavascriptDataDemo.
No records found.