B4J Tutorial AsyncStreamsObject - Send and receive objects over the network

For new projects it is recommended to use B4XSerializator instead of this solution.



SS-2013-11-14_13.26.52.png


AsyncStreamsObject allows you to send and receive objects instead of bytes.
You can read more about it here: http://www.b4x.com/android/forum/th...d-and-receive-objects-instead-of-bytes.30543/

This example connects to the same Android example and allows you to communicate with the device.
The device app acts as the server as the desktop firewalls usually blocks incoming connections.

You can download the Android example here: http://www.b4x.com/android/forum/th...e-objects-instead-of-bytes.30543/#post-202288
Make sure to update B4A RandomAccessFile library to v1.6: http://www.b4x.com/android/forum/th...handle-streams-of-any-size.30494/#post-177051

Once you have a valid connection it is very simple to send and receive custom types, drawings, collections and files.
 

Attachments

  • AsyncStreamsObject.zip
    4.1 KB · Views: 3,473
Last edited:

Asim A Baki

Active Member
Licensed User
Longtime User
Sorry I can't find it, the only attachement in the first post is AsyncStreamsObject.zip which is android
if you don't mind send me the direct link or reattach
 

Xandoca

Active Member
Licensed User
Longtime User
First, thank you Erel. You did and do a great job with B4A and B4J.
It's working.
Best Regards.
 

Xandoca

Active Member
Licensed User
Longtime User
I have to include the line server.Initialize(port,"server") on B4J side to be able to connect from device to desktop. Before I was getting "connection refused".
B4X:
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.Title = "AsyncStreamsObject Example"
    MainForm.RootPane.LoadLayout("1") 'Load the layout file.
    MainForm.Show
    MainForm.BackColor = fx.Colors.White
    astreamO.Initialize(Me, "astreamO")
    lblMyIP.Text = "My IP: " & server.GetMyIP
    cvs.Initialize("cvs")
    paneCanvas.AddNode(cvs, 0, 0, paneCanvas.Width, paneCanvas.Height)
    server.Initialize(port,"server")    '********************************************
    If File.Exists(File.DirApp, "ip.txt") Then
        txtIP.Text = File.ReadString(File.DirApp, "ip.txt")
    End If
    Log(txtIP)
End Sub
 

rayzrocket

Member
Licensed User
Longtime User
How do you know to set the 'Private port AS Int = 32118' ?
Is using port number 32118 arbitrary?
Is the port the desktop PC operating system networks to the WiFi ?, if so , how do we know this?
 

MaFu

Well-Known Member
Licensed User
Longtime User
You are not fixed to special port numbers. Use what you want, but beware of already used ports.
Used port list: link
Use a port number between 49152 and 65535. This numbers cannot be registered and therefore normally not used by companies.
 

Douglas Farias

Expert
Licensed User
Longtime User
@Erel
man i made a test, i have compiled this b4j example in my pc with java jdk1.8.0 and this works fine.
i have sent the .jar to all my friends and this works very well on all pcs.

ok
later this i made a change, i have put two radio buttons using JavaFX Scene 2.0 ok with id=radio1 and radio2
later this i have added on my code Private radio1,radio2 As RadioButton
this works fine on my pc, compile and no erros, but now the .jar dont run for my friends only for me.
i dont know why, but the .jar dont start

later this bug i have sent to my friend the jdk1.8.0 instalation, he has made the instalation and works, but only with jdk1.8.0 installed

why this? why later i have put a radio button my .jar dont work on anothers pc, need install jdk1.8.0 for all pcs for run my .jar now *-*
 

Douglas Farias

Expert
Licensed User
Longtime User
@Erel why this change the namefile?
how can i put the correct namefile, for android / b4j?
if i send to b4j my filename is = 1 ,2 ,3 +++ etc... same for b4j to b4a

how can i get the correct file name and save the file with the correct name?
 

Douglas Farias

Expert
Licensed User
Longtime User
You can pass the file name as part of the key.
dont is only this.

look at b4a code
B4X:
Sub astreamO_NewObject(Key As String, Value As Object)
    Select Key
        Case "form"
            Dim p As Person = Value
            Msgbox(p.First & " " & p.Last, "Aboo" )
            'edcomando.Text = p.First
            'edresposta.Text = p.Last
        Case "simple value"
            Dim number As Int = Value
            ToastMessageShow("Received lucky number: " & number, False)
        Case "image"


        Case "arquivo"
            Dim fileName As String = Value
            Log(fileName)
            Log("Received file. File size: " & File.Size(astreamO.TempFolder, fileName))
    End Select
End Sub

if i send arquivo:lala.png, and i get only lala.png how i go write the file?

i think need make changes on the class AsyncStreamsObject
B4X:
Private Sub astream_NewStream (Dir As String, FileName As String)
    Dim value As Object
    Dim deleteFile As Boolean = True
    If waitingForAnotherStream Then
        waitingForAnotherStream = False
        'this is the second part of the object
        Select waitingForType
            Case TYPE_BITMAP
                value = LoadBitmap(Dir, FileName)
            Case TYPE_FILE
                Log("aki: "& FileName)
                Log("aki: "& value)
                value = FileName 'just return the file name
                deleteFile = False
        End Select
    Else
        Dim raf As RandomAccessFile
        raf.Initialize(Dir, FileName, True)
        waitingForKey = raf.ReadObject(raf.CurrentPosition)
        waitingForName = raf.ReadObject(raf.CurrentPosition)
        waitingForType = raf.ReadSignedByte(raf.CurrentPosition)
        Select waitingForType
            Case TYPE_OBJECT
                value = raf.ReadObject(raf.CurrentPosition)
                raf.Close
            Case TYPE_FILE, TYPE_BITMAP
                'wait for the second part of the message
                waitingForAnotherStream = True
                raf.Close
                Log("aki: "& FileName)
                File.delete(Dir, FileName)
                Return '<--- return!!!
        End Select
    End If
    waitingForAnotherStream = False
    If deleteFile Then File.delete(Dir, FileName)
    CallSub3(target, event & "_NewObject", waitingForKey, value)
    astream.Write(waitingForName.GetBytes("UTF8"))
End Sub

Private Sub astream_NewData (Buffer() As Byte)
    Dim fileName As String = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
    File.Delete(TempFolder, fileName)
    File.Delete(TempFolder, "~" & fileName) 'delete the second part of the message if such exist
    Dim key As String = FileToKey.Remove(fileName)
    CallSub2(target, event & "_ObjectSent", key)
End Sub

here but i dont know where, i try make logs and i get only numbers
 

Douglas Farias

Expert
Licensed User
Longtime User
ok at button send i have added this
B4X:
Sub btnSendFile_Action
    Dim fc As FileChooser
    fc.Initialize
    fc.InitialDirectory = File.DirApp
    Dim name As String = fc.ShowOpen(MainForm)
    If name <> "" Then
        astreamO.WriteFile("file", "", name , "lala.png")
    End If
End Sub

on the stream class i have added this
B4X:
'Sends a file. This method doesn't support files from the asset folder.
Public Sub WriteFile (Key As String, Dir As String, FileName As String, Nome As String)
    Dim len As Long = File.Size(Dir, FileName)
    If len = 0 Then
        Log("Error getting file size.")
        Return
    End If
    Dim name(1) As String
    Dim raf As RandomAccessFile = sharedWrite(Key, name)
    raf.WriteByte(TYPE_FILE, raf.CurrentPosition)
    sharedWriteComplete(raf, name(0))
    astream.WriteStream(File.OpenInput(Dir, FileName), len)
End Sub

but i dont understand now how to use Nome on the In (Input Stream)
B4X:
    astream.WriteStream(File.OpenInput(Dir, FileName), len)
hot to add the Nome to get this on b4a?
 

Douglas Farias

Expert
Licensed User
Longtime User
ok i made this
B4X:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''' MUSICAS MUSICAS MUSICAS''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub btenviarmusicas_MouseClicked (EventData As MouseEvent)
    If listamusicas.Items.Size > 0 Then
   
   
    For i = 0 To listamusicas.Items.Size -1
    astreamO.WriteFile("arquivo:"&File.GetName(listamusicas.Items.Get(i)), "", listamusicas.Items.Get(i))
    File.GetName(listamusicas.Items.Get(i))
    Next
   
    Else
    msg.DialogType = "INFO"
    msg.Show("Sua Lista de transferências está vazia","Aboo")
   
    End If

   
'    Dim p As Person
'    p.First = "Douglas"
'    p.Last = "Farias"
'    astreamO.WriteObject("form", p)
End Sub


and on the stream class i make this
B4X:
Public Sub WriteFile (Key As String, Dir As String, FileName As String)
    Key.SubString(8)
    Dim len As Long = File.Size(Dir, FileName)
    If len = 0 Then
        Log("Error getting file size.")
        Return
    End If
    Dim name(1) As String
    Dim raf As RandomAccessFile = sharedWrite(Key, name)
    raf.WriteByte(TYPE_FILE, raf.CurrentPosition)
    sharedWriteComplete(raf, name(0))
    astream.WriteStream(File.OpenInput(Dir, FileName), len)
End Sub

the
Key.SubString(8) i get the file name, but now i dont understand how to write a file with this name. where i use this Key.SubString(8)?
 
Top