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

StarinschiAndrei

Active Member
Licensed User
Longtime User
Hi ,
I downloaded serialExemple but i can't connect to my device (BT to rs232 adapter). Can anybody tell me what's wrong ?
 

Attachments

  • Screenshot_2013-10-03-14-38-22.png
    Screenshot_2013-10-03-14-38-22.png
    32.4 KB · Views: 542
  • Screenshot_2013-10-03-14-38-36.png
    Screenshot_2013-10-03-14-38-36.png
    44.8 KB · Views: 526

StarinschiAndrei

Active Member
Licensed User
Longtime User
I try to use an BT to RS232 adapter to communicate with a scale. To return the weight i must send "W" or "P" on rs232. I tried with the code below
i checked the scale with hyperteminal and it answered if i send both characters. What's wrong in this code ?
Sub btnSend_Click
If connected Then
TextWriter1.WriteLine(txtSend.Text&Chr(10)&Chr(13))
'TextWriter1.WriteLine(AsciiToHex(txtSend.Text))
TextWriter1.Flush
txtSend.Text = ""
End If
End Sub

Sub AsciiToHex (a As String) As String
Dim bc As ByteConverter
Return bc.HexFromBytes(a.GetBytes("ASCII"))
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
i checked the scale with hyperteminal and it answered if i send both characters.
 
Last edited:

StarinschiAndrei

Active Member
Licensed User
Longtime User
It is always better to check the logs for the full error message.

Are you sure that the rs232 adapter is listening on the standard UUID?
Previous i used to test this application a samsung galaxy tab2 ..... than i tried with another device samsung galaxy S3 and with this work fine. i don't know why the tab got me the error message.
 

BluSky76

Member
Licensed User
Longtime User
Library Serial 1.23

Android 4.1.1
Kernel 3.4.0

Error:
Serial1.Initialize("Serial1")
java.io.IOException:[JSR82] accept: Connection is not created (failed or aborted)

OK:
Serial1.Initialize("Serial1")
Android 4.0.4
Kernel 2.6.32.9

On Android 4.1.1 gives me error while working on android 4.0.4.
Any idea?
 

BluSky76

Member
Licensed User
Longtime User
Erel, if I connect two devices with androit 4.0.4 or 4.2.1 there are no problems but if the dispoostivo uses Android 4.1, 4.1.1 or 4.2.0 above error occurs. When it comes to the command:

Serial1.Initialize ("Serial1")

returns error

java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted)

I believe that the serial 1.23 to 1.20 are not compatible androit 4.1 and 4.2 or Android, and has problems to manage bluetooth devices
 

BluSky76

Member
Licensed User
Longtime User
Sub Activity_Create(FirstTime AsBoolean)If FirstTime Then
Serial1.Initialize("Serial1")



Timer1.Initialize("Timer1", 200)EndIf
Activity.LoadLayout("1")
Activity.AddMenuItem("Connect", "mnuConnect")
Activity.AddMenuItem("Disconnect", "mnuDisconnect"
[FONT=verdana, geneva, lucida, lucida grande, arial, helvetica, sans-serif]End Sub



Sub Serial1_Connected (Success As Boolean)
If Success Then
ToastMessageShow("connected", False)
TextReader1.Initialize(Serial1.InputStream)
TextWriter1.Initialize(Serial1.OutputStream)
Timer1.Enabled = True
connected = True
Else
connected = False
Timer1.Enabled = False
Log(LastException.Message) *
End If
End Sub
[/FONT]

*

--------------------------------------------------------------------------------------------------

[FONT=verdana, geneva, lucida, lucida grande, arial, helvetica, sans-serif]** Activity (main) Pause, UserClosed = true **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = true **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted).
java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted).
java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted).
java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted).
java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted).
java.io.IOException: [JSR82] accept: Connection is not created (failed or aborted).
** Activity (main) Pause, UserClosed = true **
----------------------------------------------------------------------------------------------------

This error occurs on devices with Android 4.1 and 4.1.1 do not show up on devices with Android 4.0.4 and 4.2.1 i tested

[/FONT]
 

BluSky76

Member
Licensed User
Longtime User
Erel,

after updating the device firmware from 4.1.1 to 4.1.2 the problem does not occur.

I have a problem with Astreams_NewData. I receive the data correctly, but I have trouble sending multiple strings.

sub ButtonSend_Click

(first string)
send.astreams.Write (strWrite.GetBytes ("UTF8"))

do while msg.Contains ("TKZ01") = FALSE
DoEvents
loop

if the program executes the DO WHILE loop is not running Astreams_NewData.
Before sending a second string I want to know if I have received a particular string.


(second string)
send.astreams.Write (strWrite.GetBytes ("UTF8"))
end Sub
 

BluSky76

Member
Licensed User
Longtime User
Erel,

you have a solution?

because sending a command astreams.Write the program waits for the end of subsequent instructions before activating Astreams_NewData.

I have to send various commands astreams.Write and each one corresponds to a specific response. How do I read the response before sending the next command?
 

Felix Maria

Member
Licensed User
Longtime User
Hi Erel,

I have a bluetooth RFID card reader.
This program connects perfectly. But when the RFID card is flashed , the program hangs or stops responding
in the below line

B4X:
txtLog.Text = txtLog.Text & TextReader1.ReadLine & CRLF

I tried replacing the .ReadLine with the others like .ReadAll etc... But same effect. Any Advice on how to read these RFID Cards? These card may or may not have a chArACTER(10) appended to the string, But the client has already printed the cards. Please advice on how to proceed.. Thank You. Felix Maria
 

BluSky76

Member
Licensed User
Longtime User
Ernel,
There are big problems with the command, even with a module service active,

astreams.Write (strWrite.GetBytes ("UTF8"))

Using this command the sub:

Sub Astreams_NewData (Buffer () As Byte)

is not performed if after the command astreams.Write (strWrite.GetBytes ("UTF8")) there are other instructions.
So before you can make all the instructions and then activates Astreams_NewData.

Do you have a solution?
 

BluSky76

Member
Licensed User
Longtime User
Erel,

I try to explain.

I have to click a button and has to start a cycle of exchanging data with a network device or bluetooth. When I send the first command then follow automatically exchanges. the exchange is based on the response of the device.

sub send_click

first shipment
astreams.Write (writeSend.GetBytes ("UTF8"))

I check the response response of the device and sending a new string
(does not work here Astreams_NewData is activated after executing all the commands of the cycle button)

select case msg
case "AT"
astreams.Write ("OK". GetBytes ("UTF8"))
case "ATZ"
------------------
astreams.Write ("AZR". GetBytes ("UTF8"))
end select
end sub

astreams.Write ("ATZQ". GetBytes ("UTF8"))

msgbox ("Result:" & msg)

after the first shipment jumps directly to msgbox ("Result:" & msg) after pressing OK on the msgbox comes into operation Astreams_NewData.

So how to send multiple commands in a row and wait for the answer to each one?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. Don't show modal dialogs when using AsyncStreams. It may change the order of the received messages.

2. Please use [ code ] [ /code ] tags (without spaces) when posting code.

3. You will need to manage the current state.
You should check the response in Astreams_NewData

After you read the response you should send the next message. You can add the messages to a List and then send the first, read the response and send the next one.
 
Top