Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: How to get array data from JByteArray into TJavaArray



Permlink Replies: 5 - Last Post: Dec 13, 2016 3:19 PM Last Post By: Dave Nottage
Paul Gertzen

Posts: 3
Registered: 11/1/14
How to get array data from JByteArray into TJavaArray
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 12, 2016 4:49 AM
Hi,

I am trying to obtain the byte array data from a JByteArray java class which is received by a callback function (observer) in my code, this callback function receives a JObject class which could be a JInteger or a JByteArray depending on the message received, When it is a JInteger then all is fine. See below:

procedure TCallbackObserver.update(observable: Jutil_Observable; data: JObject);
Var
CallbackMessage : JCallbackMessage; // this is within the Java SDK I am using
MessageObject : JObject;
Buffer : JByte;
Msg : String;
Begin
CallbackMessage := TJCallbackMessage.Wrap((data as ILocalObject).GetObjectID);
MessageType := CallbackMessage.getMessageType;
Case MessageType Of
1 : Begin // command
Int := TJInteger.Wrap((MessageObject as ILocalObject).GetObjectID);
// Int.intValue is interpreted correctly and all is well
// ...
End;
2: Begin
// here is the problem...
Buffer := TJByte.Wrap((MessageObject as ILocalObject).GetObjectID);
Msg := JStringToString(MessageObject.getClass.getName);
// Msg at this point has a value of 'B[' which is correct from what I understand and represents a byte array
Msg := JStringToString(MessageObject.getClass.getCanonicalName);
// Msg at this point has a value of 'byte[]' which is also correct
If Buffer.getClass.isArray Then
ShowMessage('True'); // this is also correct
// now how do I get the data from the byte array into a TJavaArray so that I can use it?
????????
End;
End;
End;

I have tried numerous methods which have all failed, see below
MsgClass := MessageObject.getClass;
JNIEnv := TJNIResolver.GetJNIEnv;
Obj := (MsgClass as ILocalObject).GetObjectID;
ObjectClass := JNIEnv^.GetObjectClass(JNIEnv, Obj);
MethodID := JNIEnv^.GetMethodID(JNIEnv, ObjectClass, 'getBytes', '[B'); // returns NIL so cannot continue
// ByteArray := JNIEnv^.CallObjectMethod(JNIEnv, ObjectClass, MethodID);
// ImageSize := JNIEnv^.GetArrayLength(JNIEnv, ByteArray);
// BufferPtr := JNIEnv^.GetByteArrayElements(JNIEnv, ByteArray, Nil);

The problem seems to be that their is no TJByteArray interface class available to wrap the JByteArray java object.
Dave Nottage

Posts: 1,850
Registered: 1/7/00
Re: How to get array data from JByteArray into TJavaArray
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 12, 2016 12:26 PM   in response to: Paul Gertzen in response to: Paul Gertzen
Paul Gertzen wrote:

CallbackMessage : JCallbackMessage; // this is within the Java SDK I am using

Which SDK? Does it also contain a Java ByteArray class?

--
Dave Nottage [MVP, TeamB]
Hints, tips and tricks at: http://www.delphiworlds.com/blog
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: How to get array data from JByteArray into TJavaArray
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 12, 2016 12:53 PM   in response to: Paul Gertzen in response to: Paul Gertzen
Paul wrote:

I am trying to obtain the byte array data from a JByteArray java
class which is received by a callback function (observer) in my
code, this callback function receives a JObject class which could
be a JInteger or a JByteArray depending on the message received

You are not assigning anything to MessageObject before casting it to JInteger/JByte.
And why are you casting to JByte? That represents a single byte, not a
byte array. You should be using JByteArray or TJavaArray<Byte> instead.

--
Remy Lebeau (TeamB)
Paul Gertzen

Posts: 3
Registered: 11/1/14
Re: How to get array data from JByteArray into TJavaArray
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 12, 2016 11:33 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Paul wrote:

I am trying to obtain the byte array data from a JByteArray java
class which is received by a callback function (observer) in my
code, this callback function receives a JObject class which could
be a JInteger or a JByteArray depending on the message received

You are not assigning anything to MessageObject before casting it to JInteger/JByte.
And why are you casting to JByte? That represents a single byte, not a
byte array. You should be using JByteArray or TJavaArray<Byte> instead.

--
Remy Lebeau (TeamB)

Oops sorry, with all the copy paste to remove other items I forgot to add the MessageObject assignment to this post, this assigns message object:
CallbackMessage := TJCallbackMessage.Wrap((data as ILocalObject).GetObjectID);
MessageType := CallbackMessage.getMessageType;
MessageObject := CallbackMessage.getMessage; // JObject

I realise I shouldn't use TJByte (INTERFACE) as it is for a single byte but there is no TJByteArray (INTERFACE) and TJavaArray is a Delphi class so I cannot typecast that to an interface.

I have working java code that I am trying to translate to Delphi, below is the complete Java & Delphi function (see case 2, case 1 works perfectly)

JAVA:
public synchronized void update(Observable o, Object arg)
{
try
{
// convert the object to a callback back message.
CallbackMessage message = (CallbackMessage) arg;

int type = message.getMessageType();

switch (type)
{

case 1:
// message is a command.
Integer command = (Integer) message.getMessage();

// Analyze the command.
switch (command)
{
case 0:
strMessage = "move-no-finger";
break;
case 1:
strMessage = "move-finger-up";
break;
case 2:
strMessage = "move-finger-down";
break;
case 3:
strMessage = "move-finger-left";
break;
case 4:
strMessage = "move-finger-right";
break;
case 5:
strMessage = "press-harder";
break;
case 6:
strMessage = "move-latent";
break;
case 7:
strMessage = "remove-finger";
break;
case 8:
strMessage = "finger-ok";
break;
}

break;
case 2:
// message is a low resolution image, display it.
byte[] image = (byte[]) message.getMessage();
//
I need to reference this byte[] in delphi how?
break;
}
}
catch (Exception e)
{
alert(e.getMessage());
}
}

DELPHI:
procedure TCallbackObserver.update(observable: Jutil_Observable; data: JObject);
Var CallbackMessage : JCallbackMessage;
MessageObject : JObject;
Command : TFingerPosition;
Int : JInteger;
MessageType : Integer;
Msg : String;
Image : TJavaArray<Byte>;
JNIEnv: PJNIEnv;
Obj : JNIObject;
ObjectClass : JNIClass;
Buffer : JByte;
Begin
CallbackMessage := TJCallbackMessage.Wrap((data as ILocalObject).GetObjectID);
MessageType := CallbackMessage.getMessageType;
MessageObject := CallbackMessage.getMessage; // this is a JObject
Msg := '';
Case MessageType Of
1 : Begin // command
Int := TJInteger.Wrap((MessageObject as ILocalObject).GetObjectID);
Command := TFingerPosition(Int.intValue);
Case Command Of
MORPHO_MOVE_NO_FINGER : Msg := 'No Finger';
MORPHO_MOVE_FINGER_UP : Msg := 'Move Finger Up';
MORPHO_MOVE_FINGER_DOWN : Msg := 'Move Finger Down';
MORPHO_MOVE_FINGER_LEFT : Msg := 'Move Finger Left';
MORPHO_MOVE_FINGER_RIGHT : Msg := 'Move Finger Right';
MORPHO_PRESS_FINGER_HARDER : Msg := 'Press Harder';
MORPHO_LATENT : Msg := 'Latent Print';
MORPHO_REMOVE_FINGER : Msg := 'Remove Finger';
MORPHO_FINGER_OK : Msg := 'Finger Capture OK';
Else
Msg := IntToStr(Integer(Command));
End;
If Assigned(FBIOBase.FOnMessage) Then
FBIOBase.FOnMessage(FBIOBase, Msg, Command);
End;
2 : Begin // image
Buffer := TJByte.Wrap((MessageObject as ILocalObject).GetObjectID);
// what to do here??? I need a TJByteArray interface to "Wrap" but there isn't one MessageObject is actually a byte[]/JByteArray at this point but how do I get the
// elements out of a JByteArray into a TJavaArray?
End;
End;
End;

Thanks
Paul Gertzen

Posts: 3
Registered: 11/1/14
Re: How to get array data from JByteArray into TJavaArray
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 13, 2016 5:17 AM   in response to: Paul Gertzen in response to: Paul Gertzen
Hi Remy,

I found the solution. I needed to use JNI function WrapJNIArray as follows:
Obj := (MessageObject as ILocalObject).GetObjectID;
Image := TJavaArray<Byte>(WrapJNIArray(Obj, TypeInfo(TJavaArray<Byte>), False));

This wraps JByteArray (Obj) as TJavaArray and typecasts the result from TJavaBasicArray to TJavaArray<Byte>

There was no documentation available for WrapJNIArray (Google included) so it was only through trial and error that I eventually found this solution.

Regards,
Paul
Dave Nottage

Posts: 1,850
Registered: 1/7/00
Re: How to get array data from JByteArray into TJavaArray
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 13, 2016 3:19 PM   in response to: Paul Gertzen in response to: Paul Gertzen
Paul Gertzen wrote:

There was no documentation available for WrapJNIArray (Google included) so it was only through trial and error that I
eventually found this solution.

Good to know; thanks for posting this.

--
Dave Nottage [MVP, TeamB]
Hints, tips and tricks at: http://www.delphiworlds.com/blog
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02