Android Question ASyncStreams in Prefix mode can't send big files over Bluetooth

Leonidas Brasileiro

Member
Licensed User
Hello.

I' using ASyncStreams to send files to and from Android devices and computers. It is quite simple to use and I'm very happy about it.

Unfortunately there is an issue... Whenever I try to send files of about 200 kb and above over bluetooth, the receiving B4J app crashes, with following output:

B4X:
java.lang.RuntimeException: Message size too large. Prefix mode can only work if both sides of the connection follow the 'prefix' protocol.
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:205)
    at java.lang.Thread.run(Thread.java:745)
Error occurred on line: 219
java.lang.RuntimeException: java.util.zip.ZipException: invalid distance too far back
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readType(B4XSerializator.java:295)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:355)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.ReadObject(B4XSerializator.java:110)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.ConvertBytesToObject(B4XSerializator.java:81)
    at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:612)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:226)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:159)
    at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:90)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:61)
    at lbmdata.zepi.main._processa_sync(main.java:350)
    at lbmdata.zepi.main._astream_newdata(main.java:333)
    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:612)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:229)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:159)
    at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:90)
    at anywheresoftware.b4a.BA$3.run(BA.java:178)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.zip.ZipException: invalid distance too far back
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
    at java.io.DataInputStream.readFully(DataInputStream.java:195)
    at java.io.DataInputStream.readFully(DataInputStream.java:169)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readObject(B4XSerializator.java:349)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readMap(B4XSerializator.java:229)
    at anywheresoftware.b4a.randomaccessfile.B4XSerializator.readType(B4XSerializator.java:273)
    ... 36 more

It works fine with Wifi connection.

Line 219, referred as the one that caused the crash reads:

B4X:
fs = ser.ConvertBytesToObject(Buffer)

This line is inside this routine:

B4X:
Sub Processa_Sync(Buffer() As Byte)

    fs = ser.ConvertBytesToObject(Buffer)

   If fs.FileName = "Recebido" Then
       Log("Received all files")
   End If
    out = File.OpenOutput(File.DirData("lbmdata\zEPI\Temp"), fs.FileName, False)
    out.WriteBytes(fs.Data, 0, fs.Data.Length)
    out.Close
    localfileparts = 0
    txt_Eventos.Text = txt_Eventos.Text & "'" & fs.FileName & "' OK - " & NumberFormat2((Buffer.Length/1024),0,2,2,False) & " KB" &  CRLF
       
End Sub

Sub astream_NewData (Buffer() As Byte)
    Try
        Processa_Sync(Buffer)
    Catch
        Log(LastException.Message)
        fx.Msgbox(MainForm, "Erro: " & LastException.Message, "Exceção")
    End Try
   
End Sub

fs is a Type from this Tutorial about ASyncStreams + B4XSerializator that reads:

B4X:
Type FileToSend(FileName As String, Data() As Byte)

On the B4A side, the code is:

In 'Transferer' Service:

B4X:
Sub Envia_Arquivo(Arquivo As String)
    fs.Initialize
    fs.FileName = Arquivo
    Log(fs.FileName)
    fs.Data = Bit.InputStreamToBytes(File.OpenInput(File.DirDefaultExternal, Arquivo))
    bytes = ser.ConvertObjectToBytes(fs)
    astream.Write(bytes)   
       
End Sub

Sub astream_NewData (Buffer() As Byte)
    CallSub2(Transfere_Dados, "NewData", Buffer)

End Sub

On the 'Transfere_Dados' Activity, the code is:

B4X:
Sub NewData (data() As Byte)
    fs = Ser.ConvertBytesToObject(data)       
    Dim out As OutputStream = File.OpenOutput(File.DirDefaultExternal, fs.FileName, False)
    out.WriteBytes(fs.Data, 0, fs.Data.Length)
    out.Close
    If contador = 3 Then
        Dim ft As FileToSend
        Dim bb() As Byte
        'Signals reception to B4J
        ft.Initialize
        ft.FileName = "Recebido"
        ft.Data = Bit.InputStreamToBytes(File.OpenInput(File.DirDefaultExternal, "Semente.jsn"))
        bb = Ser.ConvertObjectToBytes(ft)
        Transferer.astream.Write(bb)
        Activity.Finish
    End If
End Sub


Why it does not work with Bluetooth?
Any ideas or workarounds?
 

Erel

Administrator
Staff member
Licensed User
What is the size of message in the B4A side and in the B4J size? Is it the same?

You can switch to astream.WriteStream. You can use InputStream.InitializeFromBytesArray to convert the array of bytes to an InputStream.

astream.WriteStream doesn't try to write the data at once so it can handle files of any size (though 200kb is not considered a large message).
 
Upvote 0

Leonidas Brasileiro

Member
Licensed User
Hello Thanks for your answer.

The app sends several JSON messages one after the other.

Message sizes match perfectly when using Wifi both on B4A and B4J sides This is what is logged:

B4X:
Log(fs.FileName & " - " & Buffer.Length & " bytes")

Identificador.jsn - 171 bytes
Entrega.jsn - 262 bytes
Entrega_APL.jsn - 265 bytes
Treinamentos_APL.jsn - 207 bytes
Treinados.jsn - 200 bytes
Treinamentos_Detalhe_APL.jsn - 147 bytes
Evidencias_Treinamento.jsn - 157407 bytes
Evidencias_Entrega.jsn - 267850 bytes
Digitais.jsn - 112 bytes

When transmitting over Bluetooth, same output on B4A. On B4J I get:

B4X:
Log(fs.FileName & " - " & Buffer.Length & " bytes")

Identificador.jsn - 171 bytes
Entrega.jsn - 262 bytes
Entrega_APL.jsn - 265 bytes
Treinamentos_APL.jsn - 207 bytes
Treinados.jsn - 200 bytes
Treinamentos_Detalhe_APL.jsn - 147 bytes

java.lang.NegativeArraySizeException
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:253)
    at java.lang.Thread.run(Thread.java:745)
java.util.zip.ZipException: invalid distance too far back

I tried switching to astream.WriteStream. Again, with Wifi no issue. I have 'ASyncInputX' files on astream.Streamfolder, as expected.

With Bluetooth, on the other hand, I get only the smallest files. B4J output is:

B4X:
Log("Dir\Filename = " & Dir & "\" & FileName)

Dir\Filename = C:\Users\Leonidas\AppData\Roaming\lbmdata\zEPI\Temp\AsyncInput1
Dir\Filename = C:\Users\Leonidas\AppData\Roaming\lbmdata\zEPI\Temp\AsyncInput2
Dir\Filename = C:\Users\Leonidas\AppData\Roaming\lbmdata\zEPI\Temp\AsyncInput3
Dir\Filename = C:\Users\Leonidas\AppData\Roaming\lbmdata\zEPI\Temp\AsyncInput4
Dir\Filename = C:\Users\Leonidas\AppData\Roaming\lbmdata\zEPI\Temp\AsyncInput5
Dir\Filename = C:\Users\Leonidas\AppData\Roaming\lbmdata\zEPI\Temp\AsyncInput6
java.lang.Exception: CRC value does not match.
    at anywheresoftware.b4a.randomaccessfile.AsyncStreams$AIN.run(AsyncStreams.java:238)
    at java.lang.Thread.run(Thread.java:745)
java.lang.Exception: CRC value does not match.

Please advise.

When working with astream.WriteStream the 'AsyncInput' files must be read with an InputStream and transformed back to bytes array, right?
 
Upvote 0
Top