Android Question file transfer using AsyncStreams + B4XSerializator

a n g l o

Active Member
Licensed User
Longtime User
learning & testing the example in https://www.b4x.com/android/forum/threads/network-asyncstreams-b4xserializator.72149/#content
, i've tried Erel's reply here 2 month back :
Read the file into an array of bytes and send the bytes:

implementing the b4a as a server on android, and the b4j as a client on windows(desktop),
and setting both sides clocks to exact same time,
the changes to Erel's original code are :
b4a :
B4X:
Sub btnSend_Click
                Dim mm As MyMessage
                Dim out As OutputStream
               
                mm.Initialize
                mm.Age = edtAge.Text
                mm.Name = edtName.Text
               
                'convert the bitmap to bytes
               
        'replace the 4  folowing lines       
                'out.InitializeToBytesArray(0)
                'cvs.Bitmap.WriteToStream(out, 100, "PNG")
                'out.Close
                'mm.Image = out.ToBytesArray
        'with the folowing 8 lines       
                Dim sharedDir As String
                Dim fileName As String
                Dim bAR () As Byte
                sharedDir=File.DirRootExternal & "/tmp"
                fileName="testo.mp3"
                bAR=Bit.InputStreamToBytes(File.OpenInput(sharedDir, fileName))
                mm.Image=bAR
                mm.Name="3.8 MB file test"
        'end replace-with
               
                CallSub2(Starter, "SendData", ser.ConvertObjectToBytes(mm))
End Sub

and :
B4X:
Public Sub SendData (data() As Byte)
    'new code
                Log(DateTime.Time(DateTime.Now))
    'end new code           
                If connected Then astream.Write(data)
End Sub

b4j :
B4X:
Sub AStream_NewData (Buffer() As Byte)
            Dim mm As MyMessage
            Dim in As InputStream
            Dim bmp As Image
    'new code
            Log(DateTime.Time(DateTime.Now))
    'end new       
            mm= ser.ConvertBytesToObject(Buffer)
            edtAge.Text = mm.Age
            edtName.Text = mm.Name
   
            'convert the array of bytes to image
    'delete the folowing 3 lines       
            'in.InitializeFromBytesArray(mm.Image, 0, mm.Image.Length)
            'bmp.Initialize2(in)
           
            'draw the image
            'cvs.DrawImage(bmp, 0, 0, cvs.Width, cvs.Height)
    'end delete           
End Sub

i've taken the times for that 3.8mb file transfer about 30 times.
all times were between 40-65 seconds, which is very SLOW (less then 100k/sec).
my network is fast and nothing heavy was occupying it.
is that the best i can get, or am i missing something ?

Thank you
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
There is no reason to use B4XSerializator if you send raw files (especially when the files are not small).

I would use AsyncStreams.WriteStream to send files. You can first send the file name with B4XSerializator and then send the data with AsyncStreams.WriteStream.

I'm not sure whether it will be significantly faster or not but it will be safer as you don't need to load the whole file into memory.
 
Upvote 0

a n g l o

Active Member
Licensed User
Longtime User
Thank you.
i've just tryed the AsyncStreams.WriteStream.
i get the same speed.
it's slow ONLY when sending the file from android to windows PC.
when using same 2 sides example to send the same file from the windows PC to android - it's 7-9 times faster.
that means that it's not a network problem, right ?
can you think of an explanation for that ?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I've tested a file transfer from Android to PC. The speed is about 2 mb (megabytes) per second.

B4A code:
B4X:
Sub Process_Globals
   Private socket As Socket
   Private astream As AsyncStreams
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
     socket.Initialize("socket")
     socket.Connect("192.168.0.6", 51042, 0)
   End If
End Sub

Sub Socket_Connected (Successful As Boolean)
   If Successful Then
     astream.InitializePrefix(socket.InputStream, False, socket.OutputStream, "astream")
   End If
End Sub

Sub Activity_Click
   astream.WriteStream(File.OpenInput(File.DirRootExternal, "b4a.mp4"), File.Size(File.DirRootExternal, "b4a.mp4"))
End Sub

B4J code:
B4X:
Sub Process_Globals
   Private server As ServerSocket
   Private astream As AsyncStreams
End Sub

Sub AppStart (Args() As String)
   server.Initialize(51042, "Server")
   server.Listen
   StartMessageLoop
End Sub

Sub Server_NewConnection (Successful As Boolean, NewSocket As Socket)
   astream.InitializePrefix(NewSocket.InputStream, False, NewSocket.OutputStream, "astream")
   server.Listen
   Log("connected")
End Sub

Sub AStream_NewStream (Dir As String, FileName As String)
   Log("completed")
   Log(File.Size(Dir, FileName))
End Sub
 
Upvote 0

a n g l o

Active Member
Licensed User
Longtime User
thank you, but i fail to get this code running. the android client fails to connect to the windows server with this code. (the ip i enter in the code
is correct - check it be 'Log(server.GetMyIP)'.)

as i understand it - this code is different from the original example as the server side here is running on the pc(b4j), and the client on android (b4a).

in the original example, the server was running on android (b4a) and the client on pc(b4j).
i've read a comment of yours explaining that it's more simple like that, as it's complicated to run server side on windows pc (permissions etc...).

maybe that's the reason that in this code, the android client fail to connect to the windows server ?
 
Upvote 0

a n g l o

Active Member
Licensed User
Longtime User
thanks,

i don't want the application to depend on manually opening windows ports or other settings.

do you know of a speed advantage when implementing the server side on windows and not on the android side ?

(i ask that trying to understand why you posted code in which the server & client switched sides.
i mean - can you reproduce the 2 mb per second when the server runs on the android side ? )

Thank you
 
Upvote 0

a n g l o

Active Member
Licensed User
Longtime User
You can try it yourself
back to sqr1...it=the first post i've sent based on your example. but here's a more compact version of the same (using WriteStream instead of write) :

b4a code :
B4X:
Sub Process_Globals
                    Private server As ServerSocket
                       Private astream As AsyncStreams
End Sub

Sub Globals
   
End Sub

Sub Activity_Create(FirstTime As Boolean)
                    If FirstTime Then
                                Log(server.GetMyIP)   
                                server.Initialize(51042, "Server")
                                   server.Listen
                    End If
End Sub

Sub Server_NewConnection (Successful As Boolean, NewSocket As Socket)
                    If Successful Then
                                   astream.InitializePrefix(NewSocket.InputStream, False, NewSocket.OutputStream, "astream")
                                   server.Listen
                                   Log("connected")
                    End If           
End Sub

Sub Activity_Click
                    Dim dirName As String
                    Dim fileName As String
                    Dim size As Long
                    Dim in As InputStream
               
                    fileName="testo.mp3"
                    dirName=File.DirRootExternal & "/tmp"
                    size=File.Size(dirName,fileName)
                    in=File.OpenInput(dirName,fileName)
                   
                    Log(DateTime.Time(DateTime.Now))
                   
                       astream.WriteStream(in, size)
End Sub

b4j code :
B4X:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
                    Private socket As Socket
                       Private astream As AsyncStreams   
End Sub

Sub AppStart (Args() As String)
                    socket.Initialize("socket")
                         socket.Connect("192.168.0.102", 51042,0)   
                    StartMessageLoop
End Sub

Sub socket_Connected (Successful As Boolean)
                       If Successful Then
                                 astream.InitializePrefix(socket.InputStream, False, socket.OutputStream, "astream")
                            astream.StreamFolder="C:\tmp"
                            Log("connected")
                       End If
End Sub

Sub astream_NewStream (Dir As String, FileName As String)
                       Log(DateTime.Time(DateTime.Now))
                       Log(File.Size(Dir, FileName))
End Sub

for 3+ mb file it takes around 1 minute.
adding a timer on the streamfolder to measure the file size during that 1 minute - found that right on start, 100-200 kb are passed, and then - no
transfer until the end when all the 3+ mb passed at once.

can you check if you reproduce 2mb/sec using this code ?

Thank you
 
Upvote 0

a n g l o

Active Member
Licensed User
Longtime User
ok...have opened the port and tried. it's slow.
it was fast for you, so i guess it's a network issue.
there was no other activity on the network, but the location of the android is quite far from the router.
maybe the wifi signal is weak there. i'll try to improve location....
Thank you
 
Upvote 0
Top