Android Tutorial Android Bluetooth / BluetoothAdmin Tutorial

Status
Not open for further replies.
Better implementation based on B4XPages:
Tutorial was rewritten in April 2018.
We will create a chat example between two Android devices.

All the non-UI code is implemented in a class named BluetoothManager. It is initialized in Service_Create of the starter service.

It is always better to implement communication related code in a service or a class initialized from a service. This way the communication state is not affected by the activities more complicated state.

The activities call the class methods directly. Calling the activities subs is done with CallSub. Remember that CallSub doesn't do anything if the activity is paused.

The first activity, the main activity, shows two buttons. One for searching other devices and one for listening for connections.

Searching other devices requires a "dangerous" permissions (see the runtime permissions tutorial for more information).
Note that you need to add the permission in the manifest editor:
B4X:
AddPermission(android.permission.ACCESS_FINE_LOCATION)

B4X:
Sub btnSearchForDevices_Click
   rp.CheckAndRequest(rp.PERMISSION_ACCESS_FINE_LOCATION)
   Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
   If Result = False Then
       ToastMessageShow("No permission...", False)
       Return
   End If
   Starter.Manager.SearchForDevices
End Sub

The second button sends an intent to the OS to make the device discoverable and then calls Serial.Listen.

Once a connection is established:
1. AsyncStreams is initialized in prefix mode (see the AsyncStreams tutorial for more information).
2. The ChatActivity is started.

SS-2018-04-04_12.02.01.jpg


Notes

- In this example we send text messages. Use B4XSerializator to send more complex types.
 

Attachments

  • Bluetooth.zip
    12.4 KB · Views: 7,033
Last edited:

Computersmith64

Well-Known Member
Licensed User
Longtime User
You should make sure that BluetoothAdmin is initialized exactly once and is a process global variable.
I'm pretty sure that's what I'm doing. I'm doing it in a service & admin is declared in Process_Globals & initialized in Service_Create. Once the transfer is complete, I stop the service then start it again if necessary. Would that count as initializing admin more than once, or is it OK because the variable is destroyed when the service is stopped?

- Colin.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I'm doing it in a service & admin is declared in Process_Globals & initialized in Service_Create
This is the problem. Process global variables are not destroyed when the service is destroyed. Check whether the object IsInitialized before you initialize it.

I recommend you to avoid stopping the service. It will do no good and will only complicate things.
 

Computersmith64

Well-Known Member
Licensed User
Longtime User
This is the problem. Process global variables are not destroyed when the service is destroyed. Check whether the object IsInitialized before you initialize it.

I recommend you to avoid stopping the service. It will do no good and will only complicate things.
OK, thanks - I'll try that. I was stopping the service because I thought it would be good practice to clean it up if it's not being used.

- Colin.
 

red30

Well-Known Member
Licensed User
Longtime User
B4X:
Dim MyMac(50) As String   
Dim U=0,m=0 As Int
Sub Admin_DeviceFound (Name As String, MacAddress As String)
    Log(Name & ":" & MacAddress)
    Dim nm As NameAndMac
    nm.Name = Name
    nm.Mac = MacAddress
        If m=0 Then
            foundDevices.Add(nm)
            ProgressDialogShow("Searching for devices (~ device founded)".Replace("~", foundDevices.Size))
            MyMac(0)=MacAddress
            m=m+1
        Else
            For i=0 To m-1
                U=0
                If MyMac(i)=MacAddress Then Exit
                U=1
            Next
            If U=1 Then
                foundDevices.Add(nm)
                ProgressDialogShow("Searching for devices (~ device founded)".Replace("~", foundDevices.Size))
                MyMac(m)=MacAddress
                m=m+1
            End If
        End If
End Sub
Corrects the multiple search error of the same device.
 

krokiz

Member
Licensed User
Longtime User
Million times "THANK YOU" for putting this information on Page 1:

"AddPermission(android.permission.ACCESS_COARSE_LOCATION)"

I was struggling for months to make my application to work on Android versions higher than 4.4.2 !

!!!!!!!!!1
 

Gianluca Esposito

Member
Licensed User
Longtime User
hi,
How do I send the following command?

Command sent:
0x8001 (Fixed)
0x0000 (Message ID)
0x00005358 (Vendor ID = CAEN SpA)
0x0021 (Message Length)
0x0000 (Reserved)
0x0008 (AVP Length)
0x0001 (AVP Type = CommandName)
0x0013 (AVP Value = InventoryTag)
0x0000 (Reserved)
0x000F (AVP Length)
0x00FB (AVP Type = SourceName)
0x536F757263655F3000 (AVP Value = “Source_0”)

Thanks
 

Beja

Expert
Licensed User
Longtime User
The tutorial and example in the first post was rewritten.

It is implemented in a more robust way and the targetSdkVersion is set to 26.

Great update.. Thanks.
worth mentioning that the new version requires B4A 8+
 

Beja

Expert
Licensed User
Longtime User
Done!.. working like a charm, very fast.. you only need to have something to say :)
 

amidgeha

Active Member
Licensed User
Longtime User
Tutorial was rewritten in April 2018.
We will create a chat example between two Android devices.

All the non-UI code is implemented in a class named BluetoothManager. It is initialized in Service_Create of the starter service.

It is always better to implement communication related code in a service or a class initialized from a service. This way the communication state is not affected by the activities more complicated state.

The activities call the class methods directly. Calling the activities subs is done with CallSub. Remember that CallSub doesn't do anything if the activity is paused.

The first activity, the main activity, shows two buttons. One for searching other devices and one for listening for connections.

Searching other devices requires a "dangerous" permissions (see the runtime permissions tutorial for more information).

B4X:
Sub btnSearchForDevices_Click
   rp.CheckAndRequest(rp.PERMISSION_ACCESS_COARSE_LOCATION)
   Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
   If Result = False Then
       ToastMessageShow("No permission...", False)
       Return
   End If
   Starter.Manager.SearchForDevices
End Sub

The second button sends an intent to the OS to make the device discoverable and then calls Serial.Listen.

Once a connection is established:
1. AsyncStreams is initialized in prefix mode (see the AsyncStreams tutorial for more information).
2. The ChatActivity is started.

SS-2018-04-04_12.02.01.jpg


Notes

- There is a potential issue on Android 8.0+ devices related to the change in the service life cycle explained here: https://www.b4x.com/android/forum/threads/automatic-foreground-mode.90546/#content
If the app is in the background for several minutes then the starter service will be destroyed and the manager will be paused until the app is killed and restarted.
A possible workaround is to call ExitApplication from Service_Destroy of the starter service.
Note that this issue will not happen with B4A 8.1+ (not released at the time of writing) as the starter service implementation will be modified in such way that it will never be paused.

- In this example we send text messages. Use B4XSerializator to send more complex types.
Hi, Is it possible to use this example to send and receive OBD data?
 
Status
Not open for further replies.
Top