Android Tutorial Android Network Tutorial

Status
Not open for further replies.
This is an old tutorial. All new implementations of network solutions should be based on AsyncStreams.

The Network library allows you to communicate over TCP/IP with other computers or devices.
The Network library contains two objects. Socket and ServerSocket.
The Socket object is the communication endpoint. Reading and writing are done with Socket.InputStream and Socket.OutputStream.

ServerSocket is an object that listens for incoming connections. Once a connection is established an event is raised and a socket object is passed to the event sub. This socket will be used to handle the new client.

Client application
Steps required:
- Create and initialize a Socket object.
- Call Socket.Connect with the server address.
- Connection is done in the background. The Connected event is raised when the connection is ready or if it failed.
- Communicate with the other machine using Socket.InputStream to read data and Socket.OutputStream to write data.

Server application
Steps required:
- Create and initialize a ServerSocket object.
- Call ServerSocket.Listen to listen for incoming connections. This happens in the background.
- Once a connection is established the NewConnection event is raised and a Socket object is passes.
- Call ServerSocket.Listen if you want to accept more connections.
- Using the Socket object received, communicate with the client.

We will see two examples.
The first example connects to a time server and displays the current date and time as received from the server.

B4X:
Sub Process_Globals
    Dim Socket1 As Socket
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
    Socket1.Initialize("Socket1")
    Socket1.Connect("nist1-ny.ustiming.org" , 13, 20000)
End Sub

Sub Socket1_Connected (Successful As Boolean)
    If Successful = False Then
        Msgbox(LastException.Message, "Error connecting")
        Return
    End If
    Dim tr As TextReader
    tr.Initialize(Socket1.InputStream)
    Dim sb As StringBuilder
    sb.Initialize
    sb.Append(tr.ReadLine) 'read at least one line
    Do While tr.Ready
        sb.Append(CRLF).Append(tr.ReadLine)
    Loop
    Msgbox("Time received: " & CRLF & sb.ToString, "")
    Socket1.Close
End Sub
We are creating a new socket and trying to connect to the server which is listening on port 13.
The next step is to wait for the Connected event.
If the connection is successful we create a TextReader object and initialize it with Socket1.InputStream. In this case we want to read characters and not bytes so a TextReader is used.
Calling tr.ReadLine may block. However we want to read at least a single line so it is fine.
Then we read all the other available lines (tr.Ready means that there is data in the buffer).

network_1.png


In the second application we will create a file transfer application, that will copy files from the desktop to the device.
The device will use a ServerSocket to listen to incoming connections.
Once a connection has been made, we will enable a timer. This timer checks every 200ms whether there is any data waiting to be read.

The file is sent in a specific protocol. First the file name is sent and then the actual file.
We are using a RandomAccessFile object to convert the bytes read to numeric values. RandomAccessFile can work with files or arrays of bytes, we are using the later in this case.
RandomAccessFile can be set to use little endian byte order. This is important here as the desktop uses this byte order as well.

The desktop example application was written with Basic4ppc.
Once connected the user selects a file and the file is sent to the device which saves it under /sdcard/android.
Both applications are attached.

Some notes about the code:
- The server is set to listen on port 2222.
The server displays its IP when it starts. The desktop client should use this IP address when connecting to a real device (this IP will not work with the emulator).
However if you work with the emulator or if your device is connected to the computer in debug mode you can use 'adb' to forward a desktop localhost port to the device.
This is done by issuing "adb forward tcp:5007 tcp:2222"
Now in the client code we should connect to the localhost ip with port 5007.
B4X:
Client.Connect("127.0.0.1", 5007)
Again if you are testing this application in the emulator you must first run this adb command. Adb is part of the Android SDK.

- Listening to connections:
B4X:
Sub Activity_Resume
        ServerSocket1.Listen
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    If UserClosed Then
        Timer1.Enabled = False
        Socket1.Close
        ServerSocket1.Close 'stop listening
    End If
End Sub

Sub ServerSocket1_NewConnection (Successful As Boolean, NewSocket As Socket)
    If Successful Then
        Socket1 = NewSocket
        Timer1.Enabled = True
        InputStream1 = Socket1.InputStream
        OutputStream1 = Socket1.OutputStream
        ToastMessageShow("Connected", True)
    Else
        Msgbox(LastException.Message, "Error connecting")
    End If
    ServerSocket1.Listen 'Continue listening to new incoming connections
End Sub
In Sub Activity_Resume (which also called right after Activity_Create) we call ServerSocket.Listen and start listening to connections. Note that you can call this method multiple times safely.
In Sub Activity_Pause we close the active connection (if there is such a connection) and also stop listening. This only happens if the user pressed on the back key (UserClosed = True).
The ServerSocket will later be initialized in Activity_Create.

The server side application can handle new connections. It will just replace the previous connection with the new one.
The desktop client example application doesn't handle broken connections. You will need to restart it to reconnect.

Edit: It is recommended to use the new AsnycStreams object instead of polling the available bytes parameter with a timer. Using AsyncStreams is simpler and more reliable.
 

Attachments

  • NetworkExample.zip
    23.7 KB · Views: 7,712
Last edited:

electro179

Active Member
Licensed User
Longtime User
for question 2
2) sorry i confused service and module code. I'm going to try with a service
 

electro179

Active Member
Licensed User
Longtime User
my second problem is resolved thank you.

Still the first.

if someone have a solution or a explanation to do a receiver broadcast

I'm looking for on other website
 

electro179

Active Member
Licensed User
Longtime User
for information

I found the problem. It's a bug on some HTC. I tried with a samsung and no problem detected.
 

joejefferies

Member
Licensed User
Longtime User
Hi I am new to Android.
I am trying to connect to a PC and tried the Basic4ppc example.
With the IP as 127.0.0.1 (localhost) I get :-

No connection could be made because the target machine actively refused it 127.0.0.1:5007
But this is just a loopback.

With a real device (with the Andoid app. running) it times out:-
A connection attempt failed because the connected party did not respond after a period of time 192.168.2.5

I am able to ping this IP reliably
I have tried turning off the (Windows) firewall

Any ideas as to why it doesn't connect.

Joe
 

joejefferies

Member
Licensed User
Longtime User
Hi
Thanks for your reply and sorry I should have made myself clearer.
As a start to developing communications from Android to and from a windows machine, I downloaded the pair of programs in your zip file. So I am running your app on an Android device and your (b4ppc) app on the windows machine. I am using the ip address provided by the andoid but the PC app is timing out.
Joe
 

dclarkchem

Member
Licensed User
Longtime User
The date and time program times out on both the emulator on my computer and my android phone when I install the APK there!
 
Last edited:

Armoured

Member
Licensed User
Longtime User
Hi Rel,
I have changed your example because the time server you have chosen isn't available:

Sub Process_Globals
Dim Socket1 As Socket
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
Socket1.Initialize("Socket1")
Socket1.Connect("nist1-pa.ustiming.org" , 13, 20000)
End Sub

Sub Socket1_Connected (Successful As Boolean)
If Successful = False Then
Msgbox(LastException.Message, "Error connecting")
Return
End If
Dim tr As TextReader
tr.Initialize(Socket1.InputStream)
Dim sb As StringBuilder
sb.Initialize
sb.Append(tr.ReadLine) 'read at least one line
Do While tr.Ready
sb.Append(CRLF).Append(tr.ReadLine)
Loop
Msgbox("Time received: " & CRLF & sb.ToString, "")
Socket1.Close
End Sub

The socket connection now works well but I have this exception:
LastException android.os.NetworkOnMainThreadException
and the program is stopped on this line:
sb.Append(tr.ReadLine) 'read at least one line

I have Basic4Android version 2.30 with the Network lib version 1.23
 

Armoured

Member
Licensed User
Longtime User
Android 4+ doesn't allow you to do any network actions on the main thread. You should use AsyncStreams instead.
Yes but I have a smartphone with Android Gingerbread 2.3 and I use api level 13 on my emulator
 

Armoured

Member
Licensed User
Longtime User
Hi Erel,
The only system to make this example working for me is to rewrite it like this:

B4X:
Sub Process_Globals
    Dim Socket1 As Socket
   Dim AStreams As AsyncStreams
End Sub

Sub Globals

End Sub 

Sub Activity_Create(FirstTime As Boolean)
    Socket1.Initialize("Socket1")
    Socket1.Connect("nist1-atl.ustiming.org" , 13, 20000)
End Sub

Sub Socket1_Connected (Successful As Boolean)
    If (Successful) Then
      AStreams.Initialize(Socket1.InputStream, Socket1.OutputStream, "AStreams")
   Else
       Msgbox(LastException.Message, "Error connecting")
      Socket1.Close
      Activity.Finish
    End If
End Sub

Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
    msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")

    Msgbox("Time received: " & CRLF & msg, "")
    Socket1.Close
   Activity.Finish
End Sub

But, repeat, I haven't Android 4.x
 
Last edited:

gampolt

New Member
Licensed User
Longtime User
Basic4ppc
---------------------------
An error occurred on sub _main_app_start.
No connection could be made because the target machine actively refused it 127.0.0.1:5007

Dear Sir,
For this problem on desktop program, how can I change IP address?
I already change app_start on File Transfer.sbp
Sub App_Start
Form1.Show
Client.New1
Client.Connect("192.168.0.112", 5007)
label1.Text = "Connection established."
End Sub

But desktop program still notify same error
 

friedhelm

New Member
Licensed User
Longtime User
Connection to time server

Hi Armoured and Erel,

after a lot of struggling and no success with the original code of Erel under Android 4.x, I finally used the same code as Armoured proposed - now it works to my full satisfaction.

Thank you, Armoured :sign0098:.

BR, Friedhelm


Hi Erel,
The only system to make this example working for me is to rewrite it like this:

B4X:
Sub Process_Globals
    Dim Socket1 As Socket
   Dim AStreams As AsyncStreams
End Sub

Sub Globals

End Sub 

Sub Activity_Create(FirstTime As Boolean)
    Socket1.Initialize("Socket1")
    Socket1.Connect("nist1-atl.ustiming.org" , 13, 20000)
End Sub

Sub Socket1_Connected (Successful As Boolean)
    If (Successful) Then
      AStreams.Initialize(Socket1.InputStream, Socket1.OutputStream, "AStreams")
   Else
       Msgbox(LastException.Message, "Error connecting")
      Socket1.Close
      Activity.Finish
    End If
End Sub

Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
    msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")

    Msgbox("Time received: " & CRLF & msg, "")
    Socket1.Close
   Activity.Finish
End Sub

But, repeat, I haven't Android 4.x
 
Status
Not open for further replies.
Top