49

Is it possible to pass a JavaScript object from JavaScript to Java using addJavascriptInterface()? Something along these lines:

var javaScriptObject = {"field1":"string1", "field2":"string2"};
JavaScriptInterface.passObject(javaScriptObject);

How would such a call be captured on the Java side? I have no problem setting up the interface to send a string, but when I send an object, I receive null on the Java end.

pheelicks
  • 7,461
  • 2
  • 45
  • 50
  • 1
    Note, make sure you your parameter is not `undefined`. I tested and it does not get converted to `null` on Java side. It becomes the string 'undefined'. – Sarsaparilla Dec 04 '20 at 01:16

6 Answers6

48

AFAIK, addJavascriptInterface() only works with primitive types and Strings, and so you cannot pass arbitrary Javascript objects.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 10
    @Robert Siemer: Use JSON, then. – CommonsWare Jul 23 '11 at 21:47
  • Or... I call some Java method once for each item in the array. I expect to have less then ten items... – Robert Siemer Jul 23 '11 at 22:03
  • @Robert Siemer: If you're not going to call it a lot, implement whichever you find easier. If it's something you do frequently, benchmark them. I don't know how much overhead there is in the JS->Java bridge. – CommonsWare Jul 23 '11 at 22:08
  • 14
    Does anybody know if there is actually any documentation on exactly what can be taken as parameters and what can be returned from a method which is part of the injected java object? – Wayne Uroda May 21 '13 at 04:07
  • 2
    @WayneUroda: Alas, I am not aware of any formal documentation. – CommonsWare May 21 '13 at 04:10
  • 3
    From my tests, you can pass any primitive, string, of array of those. in case of polymorphism, though, it appears that the method that accepts float has priority (probably a matter of ordering the methods). I'll post something about that when I have investigated further – njzk2 Sep 03 '13 at 10:16
  • @WayneUroda I'm also looking for some documentation. Does anybody know something in the mean time? – Domi May 14 '14 at 11:37
  • 1
    serialize javascript object to json string and then pass that string to the android interface. now deserialize this json string in java to a java object. – Gurpreet Jul 07 '15 at 14:15
  • hey @CommonsWare can you please share any source code/ documentation link to back this up? In my case i need to capture an integer/float(which are both same in js) and i tried with java's Number class, it did not work – ansh sachdeva Jun 08 '22 at 09:14
  • @anshsachdeva: As I wrote 9 years ago, [I am not aware of any formal documentation](https://stackoverflow.com/questions/2250917/passing-a-javascript-object-using-addjavascriptinterface-on-android/2251691?noredirect=1#comment23970810_2251691). – CommonsWare Jun 08 '22 at 11:41
  • 1
    Here is some documentation: https://chromium.googlesource.com/chromium/src/+/master/android_webview/docs/java-bridge.md#arguments-and-return-values-conversions – Heath Borders May 05 '23 at 20:54
27

This is how I am doing...

In Android...

@JavascriptInterface
public void getJSONTData(String jsonData) {
      try {
             JSONObject data = new JSONObject(jsonData); //Convert from string to object, can also use JSONArray
          } catch (Exception ex) {}
}

In JavaScript...

var obj = { Name : 'Tejasvi', Age: 100};
var str = JSON.stringify(obj);
Android.getJSONTData(str);

As of now, I could not find any other proper way to pass the native JavaScript object directly to JavascriptInterface.

Calling Android.getJSONTData({ Name : 'Tejasvi', Age: 100}) results in null (if parameter type is Object) or undefined (if parameter type is defined as String) in getJSONTData.

Tejasvi Hegde
  • 2,694
  • 28
  • 20
10

I found a solution, using JSON. My Java method returns a JSONArray, on my javascript code I receive this and convert to a javascript vector using JSON.parse(). See the example:

Java:

public class JavaScriptInterface {
Context mContext;
private static int ind=-1;
private static int [] val = { 25, 25, 50, 30, 40, 30, 30, 5, 9 };

public JavaScriptInterface(Context c) {
    mContext = c;
}

@JavascriptInterface
public JSONArray getChartData() {
    String texto = " [ {name: 'valor1', 2007: "+val[(++ind)%9]+"}, "+
                     " {name: 'valor2', 2007: "+val[(++ind)%9]+"}, "+
                     " {name: 'valor3', 2007: "+val[(++ind)%9]+"} ]"; 

    JSONArray jsonar=null;
    try {
        jsonar = new JSONArray(texto);
    } catch (JSONException e) {
        e.printStackTrace();
    }

    return jsonar;
}
}

Now the javascript code:

window.generateData = function() {
        /*var data = [ {name: 'valor1', 2007: 50},
                     {name: 'valor2', 2007: 20},
                     {name: 'valor3', 2007: 30} ];     */
        var data = JSON.parse( Android.getChartData() );
        return data;
    };

The commented code above show how it was when static, and now the data came from the Java code.

It was testes on Android 2.1 and 3.2.

James Kidd
  • 444
  • 4
  • 8
Derzu
  • 7,011
  • 3
  • 57
  • 60
9

I can run this feature

In Javascript :

var data = {
            'username' : $('#username').val().trim(),
            'password' : $('#password').val().trim(),
            'dns' : $('#dns').val().trim()
        }
        var str = JSON.stringify(data);
        Native.getLoginService(str);

In Android :

@JavascriptInterface
public void getLoginService(String jsonData){
    try{
        JSONObject data = new JSONObject(jsonData);
        String username = data.getString("username");
        String password = data.getString("password");
        String dns = data.getString("dns");

        Log.i("TAG",username + " - " + password + " - " + dns);

    }catch (Exception ex){
        Log.i("TAG","error : " + ex);
    }
}

Good luck with...

selçuk doğan
  • 406
  • 4
  • 12
3

You can't pass JSONObject or JSONArray, but you can send strings with that form and parse them to those types.

Your option is to expose the method using strings and then you can use the JSONObject or JSONArray to parse the string and use it accordingly.

Here is what I did.

@JavascriptInterface
public void passJSON(String array, String jsonObj) throws JSONException
{
    JSONArray myArray = new JSONArray(array);
    JSONObject myObj = new JSONObject(jsonObj);     
    ...

}

where array is '["string1","string2"]' and jsonObj is '{attr:1, attr2:"myName"}'

Wernight
  • 36,122
  • 25
  • 118
  • 131
SergioM
  • 1,595
  • 1
  • 15
  • 27
1

I think you can also pass JSONObject and JSONArray. So not only primitive types, but also primitive types stored in a javascript array [0,1,2] or dictionary {one:1, two:2}.

I have NOT verified this in code, just read the docs. Might be using it soon.

e mail
  • 19
  • 1
  • 5
    Where are the docs? There's only a tiny section devoted to it in WebView's documentation. – Ian Kershaw Jun 21 '11 at 11:56
  • I can confirm this, but in JS space, it is not a real Javascript array. You'll get an object with methods like length() and get(), I could only use the specific get()s like getInt(). Basically I'm pretty sure you get everything here: http://www.json.org/javadoc/org/json/JSONArray.html – Caleb Hearon May 31 '12 at 20:23