Returning byte array from Java/Android

I have several functions that make use of AndroidJavaObject.Call() to run Java code in my Unity project.

AndroidJavaObject androidUtility = new AndroidJavaObject("com.my.java.library");

androidUtility.Call("myFunctionA", data1, data2);

androidUtility.Call<bool>("myFunctionB", data1, data2);

androidUtility.Call<byte[]>("myFunctionC", data1, data2);

The functions all get called. The call to myFunctionB returns a boolean. But the call to myFunctionC returns an empty array no matter what I put in the Java code.

Does AndroidJavaObject.Call() not work when returning arrays? Is there some special processing required?

Thanks for your help.

This seems to be an issue with little knowledge, so I thought I would reply even though this thread is quite old.

The problem is that an array is not a native type, so you can’t do what you are trying in the example. Arrays, as far as I can tell, must always be transferred in the form of an Object. The Unity JNIHelper class offers a method (ConvertFromJNIArray()) to change an AndroidJavaObject into a .NET array. The array has to be an array of native types from what I can tell (except string, which isn’t native, but it still works). There is also a ConvertToJNIArray that you can use to send an array to the Java side. Hopefully the code below will shed some light on it.

C# code:
    AndroidJavaClass cls = new AndroidJavaClass("com.mycompany.myproduct.myclass");
    AndroidJavaObject obj = cls.CallStatic<AndroidJavaObject>("getStringArray");
    if (obj.GetRawObject().ToInt32() != 0)
    {
      // String[] returned with some data!
      String[] result = AndroidJNIHelper.ConvertFromJNIArray<String[]>
                            (obj.GetRawObject());
      foreach (String str in result)
      {
        // Do something with the strings
      }
    }
    else
    {
      // null String[] returned
    }
    obj.Dispose();
    cls.Dispose();

java code:
public static String[] getStringArray()
{
  String[] strs = { "Test1", "Test2" };
  return strs;   // Or alternatively, return null;
}

Pay special attention to checking for null by using the obj.GetRawObject().ToInt32() method and testing it for 0. obj itself will not be null as it is a valid object, but if you call ConvertFromJNIArray(obj) with the obj’s Raw Object value of 0, it will crash.

Also here is an example from the (docs):

// Create a java.lang.String object holding the string "some string",
// and retrieve it's hash code.
function Start() {
    var jo = new AndroidJavaObject("java.lang.String", "some string");
    var hash = jo.Call.<int>("hashCode");
}

Modified version, to return an array:

function Start() {
    var jc = new AndroidJavaClass ("com.test.test");
    var doubleArary = jc.Call.<double[]>("getDoubleArray");
}

From logcat:

03-07 11:43:35.143: I/Unity(23708): getMethodID("com.test.test", "getDoubleArray", "()[D", non-static)
03-07 11:43:35.143: I/Unity(23708): FOUND double[] test.getDoubleArray();
03-07 11:43:35.153: W/dalvikvm(23708): JNI WARNING: received null array (Check_GetArrayLength)

The called java method:

public double[] getDoubleArray() {
	return new double[] { 1, 2, 3 };
}

Using Supernat’s answer

  1. you can feed bytes to POJO
public class ReadData {
    public byte[] Buffer;
    public ReadData(byte[] buffer) {
        Buffer=buffer;
    }
  }
  1. Call your method in Android (Java) code
callback.DidReceiveDataCallback(new ReadData(data));

  1. Render the bytes in Unity
public void DidReceiveDataCallback(AndroidJavaObject bytesObj)
        {
            Debug.Log("Unity callbacks: Receive Data ");
            AndroidJavaObject bufferObject = bytesObj.Get<AndroidJavaObject>("Buffer");
            byte[] buffer = AndroidJNIHelper.ConvertFromJNIArray<byte[]>(bufferObject.GetRawObject());
           // Do something with bytes
        }