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,695
Last edited:

SergioAntunes

Member
Licensed User
Longtime User
Check the unfiltered logs. Maybe there will be something relevant.

I finally checked the logs and RFCOMM get an error 111. Nothing else jumps at me.


You can try using Connect3 or ConnectInsecure. These methods usually require you to find the correct port.

I will try. Not sure how to get the port number but I will research.

Question: there is a link on the Connect3 "help bubble" but it doesn't work on my system. What is the link address?

Thanks
 

SergioAntunes

Member
Licensed User
Longtime User
Galaxy II conclusion....

Just to close this thread....

I was unable to connect to a Galaxy II with. I tried all the suggestions but no go.

So I returned the Galaxy and purchased a Nexus 7 with 4.1.1 which is working fine.
 

YIM bunchhat

Active Member
Licensed User
Longtime User
:sign0144: .........Hello I have 1 problem about chat via bluetooth, I want to send message every time while I hold send button message was send again and again loop. Can anyone can tell me about that code?
 

YIM bunchhat

Active Member
Licensed User
Longtime User
My code use for sending data to my car remote control. What I want to do is I want to send data again and again automatic while I hold "sending button". I means data is sent loop until I release button. but it compile error......:'(
code:
Sub btnRe_Click
Do
If connected Then
TextWriter1.Write("r")
TextWriter1.Flush
End If
Loop Until btnRe.Enabled = False
End Sub
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Your code will not work for several reasons.
There is no Do ... Loop Until <condition> in Basic4android. The condition must start the block.

I recommend you to switch to AsyncStreams. Use a timer to send the command. Enable the timer when the button is down and disable it when the button is up.

If you need more help then please start a new thread for this question.
 

todh

Member
Licensed User
Longtime User
Serial Communications

I have two issues with the Serial example.
First, you need to add a menu button to poll for devices.
Second, When attempting to read data from my Bluetooth device, it hangs at txtLog.Text = txtLog.Text & TextReader1.ReadLine & CRLF. Reading the threads it looks like it is waiting for a (chr$10). I can not change the hardware and I am stuck. I tried a work around to read the 8 item menu but when I request the data I get stuck in the same place again. TextReader1.ReadLine needs to be more robust. :BangHead:
 

todh

Member
Licensed User
Longtime User
I down loaded the AsyncStreams and it would not run. I read the comments and found that InitializePrefix might need to be changed. That worked, however there are two different variables listed, AStream and AStreams. I can get the menu of eight. When I try to get the data I get a response of "you #R$". I do not know what that means or what to do about it. So I am still stuck.
 

areripe

Member
Licensed User
Longtime User
Hye, maybe this work for android that have menu button like galaxy s2 and so on, but how about Tabs 2 that not come with menu button.
Any option?
I just think to use button on the screen. But I have no idea how to do it.
hope you can help.
 

Stulish

Active Member
Licensed User
Longtime User
All the android tablets i have used have had the option button on the screen - it is normally 3 little dots (on the top or bottom of the screen), (but i have never used the tab 2)
 

walterf25

Expert
Licensed User
Longtime User
Binary Data over bluetooth

Hi Erel, i was wondering if you could help me with something, i have this bluetooth heart monitor device i'm trying to write an application for it, i can connect with the device and my phone just fine but the data sent from the device is in binary format, when i receive the data on my phone obviously is all gibberish to me, is there a way to convert that data to a readable format i can understand?

Thanks,
Walter
 

ADPTraining

Member
Licensed User
Longtime User
Bluetooth Serial download not working on tablet...

Erel, the download project from 1st post is not working with Samsung 10.1 Gallaxy Tab. Any ideas why? The issue is that the InputList is not populating. I checked the variables (pausing app) and they do show up there. Thanks in advance...
 

ADPTraining

Member
Licensed User
Longtime User
Ok, found the issue, Dumb... I was using the "Response" variable before the for/next routine. Here's the code for those who need it. I am using a Gallaxy Tab.

Sub ConnectRoutine

Dim PairedDevices As Map
PairedDevices = Serial1.GetPairedDevices
Dim DeviceList As List
DeviceList.Initialize
Dim Selection, i As Int

For i = 0 To PairedDevices.Size - 1
DeviceList.Add(PairedDevices.GetKeyAt(i)) 'add the friendly name to the list
Next
Selection = InputList(DeviceList, "Choose OBD-II Device", -1) 'show list with paired devices ****ERROR WAS HERE***

If Selection <> DialogResponse.CANCEL Then
Serial1.Connect(PairedDevices.Get(DeviceList.Get(Selection))) 'convert the name to mac address
End If

End Sub
 

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