don / cordova-plugin-ble-central

Bluetooth Low Energy (BLE) Central plugin for Apache Cordova (aka PhoneGap)
Apache License 2.0
942 stars 603 forks source link

bLE connection state on Android, unexpected disconnect #315

Closed ds949 closed 7 years ago

ds949 commented 7 years ago

When the connection is severed unexpectedly while connected then the device can't be communicated to, disconnected, or reconnected until the bluetooth is turned off and on again.

This occurs in an app close/app crash situation on android

The devices can't be connected to by other devices (including iOS and unrelated devices) until the androids bluetooth is turned off and on again.

It appears that android is persisting the connection, but is unable to use it

This issue is not present on iOS but has been observed on both android 5.0.1 and 6.0.1 Device tested SM-350, iPhone6, iPhone6s, Metawar RG

When the bluetooth enters this state ble.isConnected() calls failureCallBack ble doesn't appear on scans from multiple devices (both using and not using this ble plugin) the device reappears to all devices once the offending androids bluetooth is turned off and on again

I have tried the following:

ble.disconnect()
ble.stopNotification()
ble.stopStateNotifications()
ble.stopScan()
ble.isConnected() // failure callback

as well as writing to the bluetooth device even while not connected and flooding false bLE connections to try and overflow or disconnect

don commented 7 years ago

It does sound like Android is holding onto the connection, which shouldn't happen when the connect failure callback is called.

I think there's probably an edge case with the peripheral or Android device.

Here's how I'd suggest debugging...

Android setting -> Developer Options -> Enable Bluetooth HCI snoop log.

Run your app, get the disconnect to happen. Then move the file to your computer with 'adb pull /sdcard/btsnoop_hci.log'

Open the log file in wireshark and see what happens when the disconnect occurs.

mebrunet commented 7 years ago

Seeing the same behaviour. It only seems to happen when the connection is broken in such a way that the callback can't fire. Like when the app crashes or closes.

ds949 commented 7 years ago

I've found a hacky workaround for android via the Cordova bluetoothle plugin. Which is to simply toggle Bluetooth off and on in the background.

mebrunet commented 7 years ago

Any progress on this guys? I haven't had a chance to dig under the hood... But this is still a major problem for us.

don commented 7 years ago

@mebrunet I'd like to track this down. Can you create a simple example to duplicate this, or give me the steps to recreate with one of the sample apps?

mebrunet commented 7 years ago

That would be great. Give me an hour.

mebrunet commented 7 years ago

@don - It actually seems to be anytime you exit/re-enter the app (in android) while there is an existing connection. (At least while using the developer app, and having started a notification on a characteristic). If you don't disconnect before shutting down the app, when you reopen it the device no longer appears on any of the scans, but also can't be disconnected.

If you want a simple app that does this give me your bitbucket handle and I'll share you on something.

don commented 7 years ago

@mebrunet this might be a PhoneGap developer app (PGDA) issue that you won't see a standard app. When you run in the PGDA, the Bluetooth plugin is part of the PGDA rather than your app. This leads to odd behavior like you can close your app, but the PGDA keeps the connection in the plugin.

When you're developing on PGDA you might need to add additional hooks to disconnect Bluetooth as your app is reloading or closing. For my workshops that use PGDA I have a disconnect script that gets loaded https://github.com/don/phonegap-ble-workshop/blob/master/template/www/js/disconnector.js. It's a bit kludgy since it relies on app.disconnect(); begin globally available. You might need to change that for your app. This "fix" should only be needed for development. Alternately toggling Bluetooth on and off should do the same thing.

my bitbucket username is doncoleman

mebrunet commented 7 years ago

Little would have made me happier today than learning that this just Developer App related... But I just built out our app using PGB to double check and alas... same issue.

Is it possibly also a PGB issue?

don commented 7 years ago

If you're seeing this with PGB it likely a plugin or app issue.

An example app would help track this down. Let me know the Uuids for the peripheral and details on how to disconnect and cause the error.

mebrunet commented 7 years ago

Just shared you on a very simple repo that does this. Our app under development also has this issue.

Right now I'm just connecting to devices with Nordic's UART service 6E400001-B5A3-F393-E0A9-E50E24DCCA9E, and registering for notifications on RX 6E400003-B5A3-F393-E0A9-E50E24DCCA9E.

Closing the app while there is still a connection to the device will cause the "ghost" connection. To do this with the demo app, just click on one of the scan list items (which will connect and register notifications) then close the app. When you restart it, you won't be able to see the device in the scan list anymore.

mebrunet commented 7 years ago

Also worth noting I'm running a Nexus 5 with Android 6.0.1

don commented 7 years ago

Thanks @mebrunet I'll load 6.0.1 on my Nexus 5 and try to duplicate this.

mebrunet commented 7 years ago

@don any luck with duplication?

don commented 7 years ago

@mebrunet unfortunately I have a bunch of other stuff I need to finish before I can get back to these issues. I have some time scheduled for next week.

mebrunet commented 7 years ago

@don pinging you on this again. We've launched our new app on iOS using this plugin, but I'm holding on the Android release because of this bug. Maybe I need to better understand the scope of the issue. Are you saying that you don't see it on most Android devices? Is there anything I can do to help you on this?

mebrunet commented 7 years ago

@don and @ds949 - I did considerable digging on this and submitted a PR (#341) that addresses some of the "ghost" connections I was seeing. It would appear the Map of Peripherals was going out of sync with the connections that the BluetoothManager was holding on to. In part because of the way it was being cleared on before starting to scan.

That PR in combination with setting minSdk to 23, and always disconnecting all devices before calling navigator.app.exitApp() seems to have fully solved this problem for me.

don commented 7 years ago

@mebrunet thanks for PR #341

Raulpb49 commented 6 years ago

Hello, I seem to have the same issue of with Android Disconnection. Sorry I am not using Phone GAP. The issue is the phone sometime never or takes too long ( 50-90 secs) to connect in second connection after first disconnection. The behavior is best on Google Phones like Pixel and worst on Nexus 7.Other phones like Asus ,LG ,one Plus behaves the same though in the Sniffer I can see that Pixel and Asus, One Plus uses Same Android 7.0.x and Same Qualcomm Chip. I have read above posts and found that turning off Bluetooth programmatically and turning it On could solve the second connection issue.Is that so? Please guide, I have been going crazy for weeks debugging and finding a generic solution for this.