4

How to convert JObject to TJavaArray in DELPHI?

I tried this method but without result

var
  jvObject: JObject;
  jvArray: TJavaArray<byte>;
begin
  jvArray:= TJavaArray<byte>(jvObject);

because result of jvArray is nil.

Have anyone any idea how to solve this conversion?

3
  • What does the JObject actually represent, and why are you converting it to a byte array? Commented Sep 20, 2015 at 17:31
  • jvObject:= tBundle.get(StringToJString('pdus')); Commented Sep 20, 2015 at 17:34
  • I need it to use function TJSmsMessage.JavaClass.createFromPdu Commented Sep 20, 2015 at 17:35

1 Answer 1

0

What you are asking for is, I think, in Java terms referred to as serialising the object.

Here is a unit that does the trick:

unit SerialiseU;

interface

uses
  Androidapi.JNI.JavaTypes,
  Androidapi.JNIBridge;

//References:
//  http://docs.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html
//  http://stackoverflow.com/questions/5837698#5837739

type
  TSerialiser = class
  public
    class function Serialise(const Obj: JObject): TJavaArray<Byte>;
    class function Deserialise(Bytes: TJavaArray<Byte>): JObject;
  end;

implementation

// Delphi XE5 and later (all Android-supporting versions) offer an
// import for java.io.ByteArrayOutputStream and java.io.ByteArrayInputStream
// in Androidapi.JNI.JavaTypes.pas.
// However neither java.io.ObjectInputStream nor java.io.ObjectOutputStream
// are imported in any version up to the current (at time of writing) version,
// Delphi 10.1 Berlin, so we import the bits we need here.

type
// ===== Forward declarations =====

  JObjectInputStream = interface;//java.io.ObjectInputStream
  JObjectOutputStream = interface;//java.io.ObjectOutputStream

// ===== Interface declarations =====

  JObjectInputStreamClass = interface(JInputStreamClass)
    ['{443A1BEF-E21F-4012-A28B-4D7735136BD3}']
    {class} function init(input: JInputStream): JObjectInputStream; cdecl;//Deprecated
  end;

  [JavaSignature('java/io/ObjectInputStream')]
  JObjectInputStream = interface(JInputStream)
    ['{C1360ABB-AF58-4607-B43E-C1E1652E8FC2}']
    function readObject: JObject; cdecl;//Deprecated
  end;
  TJObjectInputStream = class(TJavaGenericImport<JObjectInputStreamClass, JObjectInputStream>) end;

  JObjectOutputStreamClass = interface(JOutputStreamClass)
    ['{D43CF30C-1E94-4D2E-A473-91EE54E41F07}']
    {class} function init(output: JOutputStream): JObjectOutputStream; cdecl;//Deprecated
  end;

  [JavaSignature('java/io/ObjectOutputStream')]
  JObjectOutputStream = interface(JOutputStream)
    ['{F4E441F8-B3D0-4463-A052-880F6644FB42}']
    procedure writeObject(&object: JObject); cdecl;
  end;
  TJObjectOutputStream = class(TJavaGenericImport<JObjectOutputStreamClass, JObjectOutputStream>) end;

{ TSerialiser }

class function TSerialiser.Serialise(const Obj: JObject): TJavaArray<Byte>;
var
  b: JByteArrayOutputStream;
  o: JObjectOutputStream;
begin
  b := TJByteArrayOutputStream.Create;
  o := TJObjectOutputStream.JavaClass.init(b);
  o.writeObject(Obj);
  Result := b.toByteArray;
end;

class function TSerialiser.Deserialise(Bytes: TJavaArray<Byte>): JObject;
var
  b: JByteArrayInputStream;
  o: JObjectInputStream;
begin
  b := TJByteArrayInputStream.JavaClass.Init(Bytes);
  o := TJObjectInputStream.JavaClass.init(b);
  Result := o.readObject;
end;

end.

This can be used like this:

uses
  SerialiseU,
  Androidapi.Helpers,
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes;
...
var
  S, S2: String;
  JS, JS2: JString;
  O: JObject;
  Bytes: TJavaArray<Byte>;
...
  // Get some Java object. In this case it is a Java java.lang.String object
  // http://d.android.com/reference/java/lang/String.html
  S := Edit1.Text;
  JS := StringToJString(S);
  // Serialise the string into a byte array
  Bytes := TSerialiser.Serialise(JS);
  // Now de-serialise the byte array back to an object
  O := TSerialiser.Deserialise(Bytes);
  // Prove that the correct object type has been de-serialised
  ShowMessageFmt('Deserialised a %s object',
    [JStringToString(O.getClass.getCanonicalName)]);
  // Cast the generic object back to a Java string
  JS2 := TJString.Wrap(O);
  // Get a Delphi string out, just to dot the 'i's and cross the 't's
  S2 := JStringToString(JS2);
  // Put the extracted string back on the UI so we can prove it all worked
  Edit1.Text := S2;
end;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.