Android Question Problem using B4XSerializator

Computersmith64

Well-Known Member
Licensed User
I am trying to send/receive some data using B4XSerializator using the subs below:

B4X:
Private Sub sendData
    Private ser As B4XSerializator
    Private Data() As Byte
    Private i As Int
    Private dataList As List
    Private rolledDiceMap(6) As Map
    Private gameDiceMap(36) As Map
    Private miscMap As Map
   
    For i = 0 To 5
        rolledDiceMap(i).Initialize
        rolledDiceMap(i).Put("value", cDie(i).Value)
    Next
    For i = 0 To 35
        gameDiceMap(i).Initialize
        gameDiceMap(i).Put("value", cGameDie(i).Value)
        gameDiceMap(i).Put("match", cGameDie(i).Match)
        gameDiceMap(i).Put("locked", cGameDie(i).Locked)
        gameDiceMap(i).Put("won", cGameDie(i).Won)
    Next
    miscMap.Initialize
    miscMap.Put("gameScore", gameScore)
    dataList.Initialize2(Array(rolledDiceMap, gameDiceMap, miscMap))
    Data = ser.ConvertObjectToBytes(dataList) 
   
    TurnBasedMatch.TakeTurn(TBMatch, Data, TurnBasedMatch.PARTICIPANT_NEXT, "GP_onTurnBasedMatchUpdated")
End Sub

Private Sub decodeMatchData(data() As Byte)
    Private i As Int
    Private ser As B4XSerializator
    Private dataList As List = ser.ConvertBytesToObject(data)
    Private rolledDiceMap() As Map = dataList.Get(0)
    Private gameDiceMap() As Map = dataList.Get(1)
    Private miscMap As Map = dataList.Get(2)
 
    For i = 0 To 5
        cDie(i).Value = Cint(rolledDiceMap(i).Get("value"))
    Next
   
    For i = 0 To 35
        cGameDie(i).Value = gameDiceMap(i).Get("value")
        cGameDie(i).Match = gameDiceMap(i).Get("match")
        cGameDie(i).Locked = gameDiceMap(i).Get("locked")
        cGameDie(i).Won = gameDiceMap(i).Get("won")
    Next
   
    Log(miscMap.Get("gameScore"))
   
End Sub

The problem I am having is that when the code hits the "cDie(i).Value = Cint(rolledDiceMap(i).Get("value"))" line, I get the following error:

java.lang.RuntimeException: Method: Get not found in: anywheresoftware.b4a.objects.collections.Map$MyMap

Is it not possible to successfully send a list of map arrays using B4XSerializator, or is there something else I'm missing here?

- Colin.
 

udg

Expert
Licensed User
Private rolledDiceMap(6) As Map
It seems you're defining a map like you would do for an array
 
Upvote 0

udg

Expert
Licensed User
cDie(i).Value = Cint(rolledDiceMap(i).Get("value"))
I am away from my PC so can't test it, but what if you write it as:
B4X:
dim m as map = rolledDiceMap(i)
cDie(i).Value = Cint(m.Get("value"))
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
I am away from my PC so can't test it, but what if you write it as:
B4X:
dim m as map = rolledDiceMap(i)
cDie(i).Value = Cint(m.Get("value"))
Yeah I thought the same thing, but haven't tried it yet because the error seemed to indicate there was a problem with using Get on the map. I'll give it a try...

- Colin.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
On further investigation & with a lot of trial & error, I have discovered that the code below will run fine in debug, however in release mode it will crash every time with the following error:

decoding
java.lang.RuntimeException: java.lang.ClassCastException: java.lang.Object[] cannot be cast to com.airlinemates.dicematch.main$_rolleddie[]
at anywheresoftware.b4a.keywords.Common$13.run(Common.java:1682)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.ClassCastException: java.lang.Object[] cannot be cast to com.airlinemates.dicematch.main$_rolleddie[]
at com.airlinemates.dicematch.main$ResumableSub_decode_BytesToObject.resume(main.java:2497)
at anywheresoftware.b4a.keywords.Common$13.run(Common.java:1680)
... 7 more

B4X:
Private Sub decodeMatchData(data() As Byte)
    Private ser As B4XSerializator
  
    Log("received")
    ser.ConvertBytesToObjectAsync(data, "decode")
  
  
End Sub

Private Sub decode_BytesToObject (Success As Boolean, NewObject As Object)
    If Success Then
        Log("decoding")
        Private msg() As Object = NewObject
        Private rd() As rolledDie = msg(0)
        Private gd() As gameDie = msg(1)
        Private i As Int
  
        For i = 0 To 5
            cDie(i).Value = rd(i).value
        Next
  
        For i = 0 To 35
            cGameDie(i).Value = gd(i).value
            cGameDie(i).Match = gd(i).match
            cGameDie(i).Locked = gd(i).locked
            cGameDie(i).Won = gd(i).won
        Next
    Else
        Log("BytesToObject Decode Failed")
    End If
  
End Sub

I've tried multiple different ways of sending / receiving the data (ie: various objects, arrays, etc...) with B4XSerializator & I always end up in the same place with then receiving device running fine in debug, but crashing in release. Arrrrggghhh! :(

Oh - here is the code I use to send the data:

B4X:
Private Sub sendData
    Log("encoding")
    Private rd(6) As rolledDie
    Private gd(36) As gameDie
    Private ser As B4XSerializator
    Private i As Int
   
    For i = 0 To 5
        rd(i).Initialize
        rd(i).value = cDie(i).Value
    Next
   
    For i = 0 To 35
        gd(i).Initialize
        gd(i).value = cGameDie(i).Value
        gd(i).match = cGameDie(i).Match
        gd(i).locked = cGameDie(i).Locked
        gd(i).won = cGameDie(i).Won
    Next
    ser.ConvertObjectToBytesAsync(Array(rd, gd), "encode")
   
End Sub

Private Sub encode_ObjectToBytes (Success As Boolean, Bytes() As Byte)
    Log("sending")
    TurnBasedMatch.TakeTurn(TBMatch, Bytes, TurnBasedMatch.PARTICIPANT_NEXT, "GP_onTurnBasedMatchUpdated")
End Sub
 
Last edited:
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Don't use arrays at all. Use lists.

B4XSerializator only works with arrays of bytes or arrays of objects (see the documentation).
So should I be able to add an array of objects to a list? My first attempt was adding an array of maps to a list, but that didn't work either. Or can it only be lists of single objects?

- Colin.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
OK - I think I understand it better now. Here's my working implementation for encoding / decoding the data I need to send / receive:

B4X:
Private Sub encodeData
    Log("encoding")
    Private listVals As List
    Private listRD As List
    Private listGD As List
    Private ser As B4XSerializator
    Private i As Int
   
    listRD.Initialize2(Array As Int(cDie(0).Value, cDie(1).Value, cDie(2).Value, cDie(3).Value, cDie(4).Value, cDie(5).Value))
    listGD.Initialize
    For i = 0 To 35
        Private GD As gameDie 'Type declared in Globals
        GD.Initialize
        GD.value = cGameDie(i).Value
        GD.match = cGameDie(i).Match
        GD.locked = cGameDie(i).Locked
        GD.won = cGameDie(i).Won
        listGD.Add(GD)
    Next
    listVals.Initialize2(Array As List(listRD, listGD))
    ser.ConvertObjectToBytesAsync(listVals, "encode")
   
End Sub

Private Sub encode_ObjectToBytes (Success As Boolean, Bytes() As Byte)
    If Success Then
        Log("sending")
        TurnBasedMatch.TakeTurn(TBMatch, Bytes, TurnBasedMatch.PARTICIPANT_NEXT, "GP_onTurnBasedMatchUpdated")
    Else
        Log("encode failed")
    End If
End Sub

Private Sub decodeMatchData(data() As Byte)
    Private ser As B4XSerializator
   
    Log("received")
    ser.ConvertBytesToObjectAsync(data, "decode")
   
End Sub

Private Sub decode_BytesToObject (Success As Boolean, NewObject As Object)
    If Success Then
        Log("decoding")
        Private listVals As List = NewObject
        Private listRD As List = listVals.Get(0)
        Private listGD As List = listVals.Get(1)
        Private i As Int
   
        For i = 0 To 5
            cDie(i).Value = listRD.Get(i)
        Next
       
        For i = 0 To 35
            Private GD As gameDie = listGD.Get(i)
            cGameDie(i).Value = GD.value
            cGameDie(i).Match = GD.match
            cGameDie(i).Locked = GD.locked
            cGameDie(i).Won = GD.won
        Next
    Else
        Log("BytesToObject Decode Failed")
    End If
   
End Sub
 
Upvote 0
Top