I am working on creating an app that can act as both a client and server for gatt connections simultaneously, but I am getting an unknown status and a disconnected state every time I run the server while it is behaving as a client.
This is the process right now:
1) Start one phone as the server (Phone1)
2) Start the other phone as the client (Phone2)
3) Connect Phone2 to Phone1 and receive notification updates about the current time.
4) Start the server gatt server on Phone2, and this is where I am getting an unknown status for my Bluetooth gatt callback. First it disconnects Phone2 from Phone1 (breaking the gatt connection), then Phone2's onConnectionStateChange for the BluetoothGattCallBack returns a disconnected state and a status code 19.
I am not really sure what could be causing this but both phones are identical Motorola XT1526 API level 22s. Is it possible this is a hardware issue where the phone cannot act as both a gatt server and client simultaneously? I have also tried using one Bluetooth adapter object for the same phone's client and server, but also two separate Bluetooth adapter objects. Any help would be greatly appreciated.
According to Bluetooth specification (Bluetooth Spec 4.2 Vol. 6 part B 4.5: Connection State):
"There shall be only one connection between two LE device addresses.
An initiator shall not send a connection request to an advertiser it is already connected to.
If an advertiser receives a connection request from an initiator it is already connected to, it shall ignore that request."
It's possible that Android phones prevent such situations with disconnection, cause I have the same problem here.
Related
I have confusion on bluetooth connections.
Preface: when connecting devices for android over bluetooth you can connect as server or as client
My understand: connecting as the server essentially means that your device will be hosting the connection. Connecting as client means that you are being hosted by another device - and/or the device you are connecting to is the host.
I am trying to build an app that can connect via bluetooth and control a device. My first use case is my TV. so I want to make my app that can connect to my TV and control it as a remote. My initial thought is that the TV would act as the server. If I am connecting to another phone then I would imagine that my device would need to be the server. In most cases, if I want my app to act as a controller to send control signals to the device it connects to - is it correct to assume that my device is client or server?
Assuming that you mean Bluetooth Low Energy (BLE), then there are two separate types of roles that dictate how communication happens in Android:-
Central vs Peripheral - This has to do with the connection establishment and maintenance as follows:-
Peripheral device is the one responsible for advertising its presence as well as accepting incoming connections. Sensors usually fall into this category.
Central device is the one responsible for scanning and establishing the connection with the remote peripheral device. Phones usually fall into this category.
GATT client vs GATT server - This dictates how communication is handled when that connection is made:-
GATT server is the device that hosts all the data. Again, sensors usually fall into this category.
GATT client is the device that reads the data from the GATT server. Again, phones and computers usually take the GATT client role.
The two types of roles are separate (i.e. a Central can be a GATT server or a GATT client, and vice versa), but in the majority of the cases, the central is the GATT client.
And to finally answer your question, I would make the remote controller to be both the central and the GATT client. This way your TV would always be advertising its presence and hosting the date, while the remote scans/connects and reads/writes to that data.
You can find more information in the links below:-
The ultimate guide to Android BLE development
Bluetooth Low Energy: A primer
Android BLE examples
Client because when is server tv, you can connect from more clients (mobiles).
When is server mobile you can controll more tvs, but tv can connect only to defined mobiles.
I have a setup with two Android devices: an android phone and a custom hardware running Android 10. The latter acts as a BLE Server, which is discoverable always with the same static MAC address. Also when that custom HW is paired with the phone it has access to phone's contacts and calls history. That HW can also play media (sound) streamed from the phone.
I use RxAndroidBle 1.11.0 library for BLE communication. As soon as I exchange some data via BLE Characteristic I unsubscribe from the RX observable so the library effectively calls: bluetoothGatt.disconnect() then blutetoohGatt.close()
(all those inside the DisconnectOperation class).
My problem is the fact that based on my observations, calling blutetoohGatt.disconnect() disconnects the classic BT profile (PBAP) as well.
Is it an expected behaviour?
I have investigated the code of generic Android P framework and it looks that calling bluetoothGatt.disconnect() -> bluetoothGatt.close() completely disconnects the device described by the given MAC Address:
BluteoothGatt#disconnect()
BlutetoothGatt#close()
BlutetoothGatt#unregisterApp()
I would risk a statement that I have quite unusual BLE use-case scenario where the phone (Central/Client) and the peripheral (custom Android HW/Server) are connected simultaneously via Classic BT profile and via BLE.
I suspect that disconnecting/closing device using its BT MAC address disconnect both profiles, hence the contacts sharing stops working.
Is it possible to disconnect BLE connection only, but not affect the classic BT (SPP/PBAP) connections between the two devices?
After further investigation described on that Github issue
I realised that my custom hardware is equipped with dual-mode BT adapter so it supports classic BT (BR/EDR) and the BLE one.
As soon as I pair an Android phone with the custom hardware via System Settings, classic BT profiles are bonded, but also my GATT Server advertises relevant services using the same MAC address which is used by the BR/EDR. Disconnecting BLE client connection disconnect BD/EDR as well.
What helps in my case is to not start pairing via System Settings, but let the GATT server advertise and let my BLE client app to connect (and trigger pairing) first. As a result I have a BLE connection with server available under "AA:AA:AA:AA:xx", while the classic BT profiles are connected to "BB:BB:BB:BB:yy" interface on the custom hardware.
Now, disconnecting BLE profile does not disconnect the classic one.
I am looking for a solution which would allow my GATT Server to be advertised with BLE only, but no luck so far.
Here are some interesting links I have found:
connectGatt creates connection over BT Classic instead of BLE
how to force BLE "just works" pairing in Android
BLE Dual-Mode
I'm developing an Android Things app (Dev Preview 6.1, Raspberry Pi) with a GATT server. When a connected client app disconnects, my device has stopped advertising. However, the custom client app (out of my control) is written in such a way that it needs to disconnect between reads/writes, then reconnect.
I know that I can restart advertising upon disconnect, but since it has a new (pseudo-)MAC address, the client can't automatically reconnect.
FWIW, I see the same behavior in this sample (& using nRF Connect as a test clinet): https://github.com/androidthings/sample-bluetooth-le-gattserver
Is there way to keep the GATT server advertising in this case? Or can I specify the advertised device address so that I can keep it consistent across advertisements?
It turns out this is a known bug in Android Things: https://issuetracker.google.com/issues/70269277
I have a Bluetooth device which is connected to Android smartphone over Bluetooth SPP profile.
Once connection is successful, device opens the rfcomm device
handle = open("/dev/rfcomm0", O_RDWR | O_NOCTTY | O_SYNC);
After successful connection smartphone sends data to device.
It sends 3 consecutive messages of few bytes to device. This is verified after looking at snoop log of Bluetooth device.
However the blocking read at Bluetooth device side is never able to read initial 2 messages, after that it reads all other messages.
Same experiment is tried by writing a standalone script which starts reading data on rfcomm device as soon as SPP connection is successful, but here also outcome is same.
Please guide what might go wrong.
More or less it was a timing issue.
The app on device requests Bluetooth stack to create SPP connection with Android phone. On successful SPP connection /dev/rfcomm0 device is created by Bluetooth stack.
As soon as rfcomm channel is created, Android phone sends data to device but by this time application on device was not updated with the creation of rfcomm device. As there are no readers for rfcomm, Bluetooth stack flushes all data it received from Android phone.
Performed this experiment multiple times, once it worked.
I have an application that needs to keep the bluetooth discovery process in a loop to always discover new bluetooth devices (when the BroadcastReceiver gets a BluetoothAdapter.ACTION_DISCOVERY_FINISHED, I just call the startDiscovery() again). I've recently added some socket communication to the app, that basically opens a Socket to a server, sends data and then closes the socket.
When I'm using 3G, everything works fine and a sniffer shows no TCP Retransmissions, the socket is cleanly opened and closed. Using Wifi, however, shows lots of TCP Retransmissions and sometimes even failures to connect the socket (with java.net.SocketException timeout).
I'm using a Samsung Galaxy S with Android 2.2.1. Is there something I'm overlooking?
Can you try to configure and move WiFi to a different channel ? If you are using WiFi also in the 2.4 GHz band interference is expected specially during initial discovery / connection, after connection it should become better as Bluetooth should frequency hop to avoid interference (unless WiFi is clogging the complete spectrum)