Android Tutorial Android Serial tutorial

The code in this tutorial should not be used for new projects.
New tutorial:
https://www.b4x.com/android/forum/threads/android-bluetooth-bluetoothadmin-tutorial.14768/#content

This tutorial covers the Serial library. This library allows you to connect with other Bluetooth devices using virtual serial ports (RFCOMM).

The Serial library requires Android OS 2.0 or above (API level 5 or above).

We will build a simple chat example which allows two connected devices to send text messages.


serial_chat2.png


We created a process global object named Serial1 of type Serial.
Usually it is a good idea to initialize process objects in Sub Activity_Create when FirstTime is True. This way the objects will be initialized exactly once.

B4X:
Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        Serial1.Initialize("Serial1")
        Timer1.Initialize("Timer1", 200)
    End If
    Activity.LoadLayout("1")
    Activity.AddMenuItem("Connect", "mnuConnect")
    Activity.AddMenuItem("Disconnect", "mnuDisconnect")
End Sub
The next Sub running is Activity_Resume:
B4X:
Sub Activity_Resume
    If Serial1.IsEnabled = False Then
        Msgbox("Please enable Bluetooth.", "")
    Else
        Serial1.Listen 'listen for incoming connections
    End If
End Sub
Here we are checking if the Bluetooth device is enabled. If it is not enabled we ask the user to enable it. Note that by putting this code in Activity_Resume (and not Activity_Create) this test will happen every time the activity is resumed. So if the user goes to the settings screen, enables the device and then returns to our application we will now know that the Bluetooth is enabled.

If the Bluetooth is enabled we start listening for incoming connections. This allows other devices to connect with our device. This is not required if you connect to a device that listens for connections (like external GPS for example).
Note that calling Listen more than once doesn't do anything. So we are safe calling it this way.

When the user presses on the Connect menu item we show the user the list of known paired devices. When the user clicks on a device name we fetch its MAC address from the map and connect to it:

serial_chat_1.png


B4X:
Sub mnuConnect_Click
    Dim PairedDevices As Map
    PairedDevices = Serial1.GetPairedDevices
    Dim l As List
    l.Initialize
    For i = 0 To PairedDevices.Size - 1
        l.Add(PairedDevices.GetKeyAt(i)) 'add the friendly name to the list
    Next
    Dim res As Int
    res = InputList(l, "Choose device", -1) 'show list with paired devices
    If res <> DialogResponse.CANCEL Then
        Serial1.Connect(PairedDevices.Get(l.Get(res))) 'convert the name to mac address
    End If
End Sub
The connection is not established immediately. It will happen in the background. When the connection is established, the Connected event will be raised. A 'Success' parameter tells us if the connection is successful.
The Connected event can also be raised if an incoming connection is established.

B4X:
Sub Serial1_Connected (Success As Boolean)
    If Success Then
        ToastMessageShow("Connected successfully", False)
        TextReader1.Initialize(Serial1.InputStream)
        TextWriter1.Initialize(Serial1.OutputStream)
        timer1.Enabled = True
        connected = True
    Else
        connected = False
        Timer1.Enabled = False
        Msgbox(LastException.Message, "Error connecting.")
    End If
End Sub
If the connection was established successfully we can start the data transfer.
TextReader1 and TextWriter1 are process global object. We now initialize them using the serial stream. This will allow us to send and receive text over our newly created connection.
Timer1 is used to test whether there is incoming data (and read this data). Now we enable it and start listening.

If the connection is not successful we retrieve the exception and show it.

Sending messages - When the user presses on btnSend we send the text:
B4X:
Sub btnSend_Click
    If connected Then
        TextWriter1.WriteLine(txtSend.Text)
        TextWriter1.Flush
        txtSend.Text = ""
    End If
End Sub
'connected' is a variable that we use to know if we are currently connected.
Note that we call Flush after writing the text. This way we make sure that TextWriter doesn't buffer the text and sends it right away.

Receiving messages - Whenever the timer ticks we check if there is any data waiting to be read. If there is, we read it and add it to the large EditText:
B4X:
Sub Timer1_Tick
    If connected Then
        If TextReader1.Ready Then 'check if there is any data waiting to be read
            txtLog.Text = txtLog.Text & TextReader1.ReadLine & CRLF
            txtLog.SelectionStart = txtLog.Text.Length
        End If
    End If
End Sub
TextReader.ReadLine is a blocking call. It waits till there is at least a single character to be read. Therefore we need to test TextReader.Ready if we don't want to block our application.

This application can also be used to connect with non-Android devices.
An external GPS for example:
serial_3.png


The external GPS continuously sends its data as text.
I actually had quite an interesting conversation with the external GPS...

The program is attached.

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

  • SerialExample.zip
    6.3 KB · Views: 10,692
Last edited:

saintanger

New Member
Licensed User
Longtime User
I'm New with basic4android

Greetings guys,

:sign0085:I would like to ask a question about that simple code.

I want to implement that bluetooth chat, but what I really want for this is that if the scanned device name is a URL to be able for the user to click on the url and to send him with the browser to the link, or if its possible to display the picture if the link address is an image right in the application.

I've seen that showing images from URL address is possible in the android application.

Well, Thanks a Lot in advance, and Support would be highly appreciated cause I just recently started with b4a(yesterday).

Kind Regards,:sign0089:
Dennis Tod.
 

saintanger

New Member
Licensed User
Longtime User
Little confused.

Thank you Erel for your quick reply,

well lets say that i want in that code string
StartActivity (PhoneIntents.OpenBrowser("http://www.google.com"))
to have in the place thats "http://www.google.com" a line for each bluetooth name's device. Could you give me a hand with that? I'm really confused :sign0085:

And thank you once again!

Kind Regards, :sign0089:
Dennis Tod.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
This code (taken from the example in the first post) adds the names to a list:
B4X:
    For i = 0 To PairedDevices.Size - 1
        l.Add(PairedDevices.GetKeyAt(i)) 'add the friendly name to the list
    Next
Assuming that the name is a valid URL, which I'm not sure is possible, you should save the value and later use it to start the browser activity.
 

anormal

Member
Licensed User
Longtime User
hi, i've tried to modify this example for using asyncstreams (i want to do bluetooth read only inside a service), but i have problems with the initialization of the layout,

i've tried to initializate textereader1 and textwriter before calling aestreams.iniatializeprefix ... but i got the same error? :(


Error:

main_activity_create (B4A line: 23)
AStreams.InitializePrefix(Serial1.InputStream, False, Serial1.OutputStream, "AStreams")
java.lang.NullPointerException
at anywheresoftware.b4a.objects.Serial.getInputStream(Serial.java:195)
at anywheresoftware.b4a.samples.serial.main._activity_create(main.java:236)

This is the code i've modified:
========================================
B4X:
'Activity module
Sub Process_Globals
   Dim AStreams As AsyncStreams
   Dim Serial1 As Serial
   Dim TextReader1 As TextReader
   Dim TextWriter1 As TextWriter
   'Dim Timer1 As Timer
   Dim connected As Boolean
End Sub

Sub Globals
   Dim btnSend As Button
   Dim txtLog As EditText
   Dim txtSend As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("1")
   Activity.AddMenuItem("Connect", "mnuConnect")
   Activity.AddMenuItem("Disconnect", "mnuDisconnect")
   If FirstTime Then
      Serial1.Initialize("Serial1")
      AStreams.InitializePrefix(Serial1.InputStream, False, Serial1.OutputStream, "AStreams")
      'Timer1.Initialize("Timer1", 200)
   End If
End Sub
Sub Activity_Resume
   If Serial1.IsEnabled = False Then
      Msgbox("Please enable Bluetooth.", "")
   Else
      Serial1.Listen 'listen for incoming connections
   End If
End Sub
Sub mnuConnect_Click
   Dim PairedDevices As Map
   PairedDevices = Serial1.GetPairedDevices
   Dim l As List
   l.Initialize
   For i = 0 To PairedDevices.Size - 1
      l.Add(PairedDevices.GetKeyAt(i))
   Next
   Dim res As Int
   res = InputList(l, "Choose device", -1) 'show list with paired devices
   If res <> DialogResponse.CANCEL Then
      Serial1.Connect(PairedDevices.Get(l.Get(res))) 'convert the name to mac address
   End If
End Sub

Sub Serial1_Connected (Success As Boolean)
   If Success Then
      ToastMessageShow("Connected successfully", False)
      TextReader1.Initialize(Serial1.InputStream)
      TextWriter1.Initialize(Serial1.OutputStream)
      'timer1.Enabled = True
      connected = True
   Else
      connected = False
      'Timer1.Enabled = False
      Msgbox(LastException.Message, "Error connecting.")
   End If
End Sub
Sub mnuDisconnect_Click
   Serial1.Disconnect
   AStreams.Close
   connected = False
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnSend_Click
   If connected Then
      TextWriter1.WriteLine(txtSend.Text)
      TextWriter1.Flush
      txtSend.Text = ""
   End If
End Sub

Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
   If connected Then   
       msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
      txtlog.text = txtlog.Text & msg & CRLF
      txtlog.SelectionStart = txtlog.Text.Length
       'ToastMessageShow(msg, False)
   End If 
End Sub

'Sub Timer1_Tick
'   If connected Then
'      If TextReader1.Ready Then 'check if there is any data waiting to be read
'         txtLog.Text = txtLog.Text & TextReader1.ReadLine & CRLF
'         txtLog.SelectionStart = txtLog.Text.Length
'      End If
'   End If
'End Sub
 

saintanger

New Member
Licensed User
Longtime User
No device searching?

well there is no search for new devices? when pressing connect it displays only the devices that have been already paired.

That can't be worked out? I really need this feature.:sign0085:
 

ondesic

Active Member
Licensed User
Longtime User
If you are paired, but not connected, do you have to be in discovery mode to connect?
 

ejoeler

New Member
Licensed User
Longtime User
Serial.Enable

Hello Erel,

In the documentation of Serial 1.2 there is a method called Enable which I can not find.

I declare

Dim Serial1 As Serial

Any idea?

Best Regards

Joel
 

ta1dr

Member
Licensed User
Longtime User
dear Erel
I tried AsyncStreams but I didnt received any data also I didnt sent and data
when I send data like tis "hello" + chr(10) vbasic , apk down my code below
could you write sample code serial and AsyncStreams ?

B4X:
'Activity module
Sub Process_Globals
    Dim AStreams As AsyncStreams
   Dim Serial1 As Serial
   
   'Dim TextReader1 As TextReader
   Dim TextWriter1 As TextWriter
   'Dim Timer1 As Timer
   Dim connected As Boolean
End Sub

Sub Globals
   Dim btnSend As Button
   Dim txtLog As EditText
   Dim txtSend As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      Serial1.Initialize("Serial1")
      'Timer1.Initialize("Timer1", 200)
      'AStreams.InitializePrefix(Serial1.InputStream, False, Serial1.OutputStream, "AStreams")
   End If
   Activity.LoadLayout("1")
   Activity.AddMenuItem("Connect", "mnuConnect")
   Activity.AddMenuItem("Disconnect", "mnuDisconnect")
End Sub
Sub Activity_Resume
   If Serial1.IsEnabled = False Then
      Msgbox("Please enable Bluetooth.", "")
   Else
      Serial1.Listen 'listen for incoming connections
   End If
End Sub
Sub mnuConnect_Click
   Dim PairedDevices As Map
   PairedDevices = Serial1.GetPairedDevices
   Dim l As List
   l.Initialize
   For i = 0 To PairedDevices.Size - 1
      l.Add(PairedDevices.GetKeyAt(i))
   Next
   Dim res As Int
   res = InputList(l, "Choose device", -1) 'show list with paired devices
   If res <> DialogResponse.CANCEL Then
      Serial1.Connect(PairedDevices.Get(l.Get(res))) 'convert the name to mac address
   End If
End Sub

Sub Serial1_Connected (Success As Boolean)
   If Success Then
      ToastMessageShow("Connected successfully", False)
      AStreams.InitializePrefix(Serial1.InputStream, False, Serial1.OutputStream, "AStreams")
      'TextReader1.Initialize(Serial1.InputStream)
      'TextWriter1.Initialize(Serial1.OutputStream)
      'timer1.Enabled = True
      connected = True
   Else
      connected = False
      'Timer1.Enabled = False
      Msgbox(LastException.Message, "Error connecting.")
   End If
End Sub
Sub mnuDisconnect_Click
   Serial1.Disconnect
   connected = False
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnSend_Click
   If connected Then
      TextWriter1.WriteLine(txtSend.Text)
      TextWriter1.Flush
      txtSend.Text = ""
   End If
End Sub
'Sub Timer1_Tick
'   If connected Then
'      If TextReader1.Ready Then 'check if there is any data waiting to be read
'         txtLog.Text = txtLog.Text & TextReader1.ReadLine & CRLF
'         txtLog.SelectionStart = txtLog.Text.Length
'      End If
'   End If
'End Sub
Sub AStreams_NewData (Buffer() As Byte)
    Dim msg As String
    If connected Then    
        msg = BytesToString(Buffer, 0, Buffer.Length, "UTF8")
        txtlog.text = txtlog.Text & msg & CRLF
        txtlog.SelectionStart = txtlog.Text.Length
        'ToastMessageShow(msg, False)
    End If 
End Sub
 

ta1dr

Member
Licensed User
Longtime User
Hi Erel;
thanks for help
ok my code send data but not received I send data from pc ( vbasic prg) and my apk crash .

my test;
send by galaxy tab ABCDE
I see my pc 0x05,0x00,0x00,0x00,0x41,0x42,0x43,0x44,0x45 (0x41 is hex value )
firsst value ( 0x05) I think buffer count but I didnt know 0x00
 
Last edited:

ta1dr

Member
Licensed User
Longtime User
ok I succeed
yes I can send data from PC to android only one time I want to send again but my android device no received data and not crash

my pc code like this;

B4X:
Private Sub Command1_Click()
    MSComm1.OutBufferCount = 0
    MSComm1.Output = Chr(3) & Chr(0) & Chr(0) & Chr(0) & Chr(65) & Chr(66)& Chr(67) & Chr(10)
End Sub

and I see my android device and serial apk "ABC"
 
Last edited:

ta1dr

Member
Licensed User
Longtime User
I removed LF { chr(10) } my pc code .All ok no any problems
B4X:
Private Sub Command1_Click()
    MSComm1.OutBufferCount = 0
    MSComm1.Output = Chr(3) & Chr(0) & Chr(0) & Chr(0) & Chr(65) & Chr(66)& Chr(67) 
End Sub

if chr(3) is buffer number what's that mean chr(0),chr(0),chr(0) ?
 

chuckw

New Member
Licensed User
Longtime User
Bluetooth_admin

When it gets to the line Serial.Listen, I get the message: "Last Exception java.lang.Security.Exception: Need BLUETOOTH_ADMIN permission: Neither user 10075 nor current process has android.permission.BLUETOOTH_ADMIN".

How do I set the BLUETOOTH_ADMIN?
 

Similar Threads

  • Locked
  • Article
Android Tutorial Android JSON tutorial
Replies
90
Views
164K
  • Locked
  • Article
Android Tutorial SQL tutorial
Replies
161
Views
284K
  • Locked
  • Article
Android Tutorial GPS tutorial
Replies
310
Views
263K
Top