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.
Related
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
Trying to connect an Android phone to a somewhat unusual, nonstandard BLE device (a blood pressure monitor). Data points:
My program connects and reads other BLE devices fine.
My program sees the device in a BLE scan, but won't connect. Instead I get an immediate "Disconnected" status with a generic GATT_ERROR (status code 0x85).
Nordic's Android BLE scanner app will connect and read/write the device.
The device uses an unknown Service (FFF0) with one characteristic (FFF1) for notifications from the device and another (FFF2) to write commands to it.
The TI BLE packet sniffer software seems to indicate that no connection request is ever sent to the device.
Here's what I've observed with the Nordic scanner app:
When you turn the device on, it advertises and the app can connect to it. If you then enable Notifications on FFF1, you receive a byte 0xA5; this is per the device spec, which says it sends this byte every 500 ms. The (rather rudimentary) docs say this is "waiting for the connection" but obviously it is already connected.
If you then write the specified "start" command string to FFF2, it starts taking a reading and appears to perform correctly.
The Nordic app can connect; why can't mine?
Update: have verified that the Nordic app works on the same Android phone that is running my program.
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.
Is there a way to send files via bluetooth without pairing in android?
Here's a part of doc which I found here. RFCOMM channels is used here for bluetooth communications. This might help you in understanding that pairing is necessary.
paired means that two devices are aware of each other's existence,
have a shared link-key that can be used for authentication, and are
capable of establishing an encrypted connection with each other. To be
connected means that the devices currently share an RFCOMM channel and
are able to transmit data with each other. The current Android
Bluetooth API's require devices to be paired before an RFCOMM
connection can be established.
Again below,
If the two devices have not been previously paired, then the Android
framework will automatically show a pairing request notification or
dialog to the user during the connection procedure. So when attempting to connect devices, your application does not need to be concerned about whether or not the devices are paired. Your
RFCOMM connection attempt will block until the user has successfully
paired, or will fail if the user rejects pairing, or if pairing fails
or times out.
I need to use Bluetooth for communication with another application which sends data via bluetooth SPP profile. I use the Bluetooth Chat app from Android developer site. I am using real phone (HTC Desire) as there is no Bluetooth API in Android emulator. I use a BlueSoleil bluetooth dongle.
When the other application tries to connect to my phone via Bluetooth and send data via SPP, it is not possible to connect the phone to the application. So I tried Windows Hyperterminal to send data and connect the phone through the dongle. In this situation, I can receive the data and display on the phone.
I would like to know how to find out which bluetooth profile was used when communicating with Hyperterminal.
I have read that bluetooth stack has a buggy implementation in HTC Desire and the SPP profile doesn't work consistently always.
Appreciate any suggestion and time spent on this.
Cheers,
Madhu Nandan
In the case of your Hyperterminal communication - SPP profile that was most likely used.
SPP profile is a generic profile that just establishes the RFCOMM data channel and sets up a virual COM port for applications to open and connect to and send data.
SPP does not specify any data formats or application level communication protocol to be used by application.
So applications at both end should establish the required format/protocol for communication.
Applications sets it selfs up on a virtual COM (over SPP) and advertises itself (on SDP) via a unique UUID (And Service Names)
So I would suggest that you use the chat application as a starting point, and start with connection / reading data etc, then modify it and complete the application that talks to your application on the device.
(The chat example is meant to work with a remote chat of the same type and is not a generic usage for SPP profile application)
Hope this helps you.