Giter VIP home page Giter VIP logo

android-ble-library's People

Contributors

0xmyon avatar archie94 avatar bgiori avatar corentin-c avatar cydragon80 avatar electronicspacecat avatar groovelab avatar henrylcs avatar himalia416 avatar huntc avatar kkkbird avatar ligi avatar maragues avatar muscardinus avatar peabody124 avatar philips77 avatar sssemil avatar sylwester-zielinski avatar tfkamran avatar thibaud-denche avatar usikder avatar xabiergoros avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-ble-library's Issues

Task: Migrate to AndroidX

The Android Jetpack is stable now. This lib would only use the annotations from AndroidX.
Importing the lib as a module to projects already migrated requires the lib also to be migrated.

[Version 1.2] BleManagerGattCallback.nextRequest stucks after onBonded

Hi,

I ran into the mentioned issue using version 1.2.0 of the library. The app is running on a Nexus 5 with Android 8.1.
I'm trying to connect to a nRF52840 dongle, then bond. After bonding I want to change MTU size and write some characteristics on the device.

The flow in details:

  • after device discovery, I call BleManager.connect(BluetoothDevice)
  • in my BleManagerGattCallback.initGatt implementation, I push a single bond request (Request.createBond()) into the requests queue
  • BleManageCallbacks.onBondingRequired(BluetoothDevice) is invoked, Android pops up the Pairing notification, where I choose to pair. In the nRF Connect app, I also confirm that the pins match.
  • BleManagerCallbacks.onBonded(BluetoothDevice) is invoked. In my implementation I enqueue a new MTU change request here: enqueue(Request.newMtuRequest(128))

The request never gets processed since the BleManager.BleManagerGattCallback.mOperationInProgress flag is still true.

I actually checked out the source of the library and modified the BleManager implementation to reset the mOperationInProgress flag to false on successful bonding in the BroadcastReceiver's BOND_BONDED case:

                                        Logger.i(mLogSession, "Device bonded");
					mGattCallback.mOperationInProgress = false; // added this line
					mCallbacks.onBonded(device);
					// If the device started to pair just after the connection was established the services were not discovered.
					if (mBluetoothGatt.getServices().isEmpty()) {
						mHandler.post(() -> {
							Logger.v(mLogSession, "Discovering Services...");
							Logger.d(mLogSession, "gatt.discoverServices()");
							mBluetoothGatt.discoverServices();
						});
						return;
					}
					break;

With the modifications above I managed to run the MTU change and other requests after bonding.

Is my solution valid or did I do something wrong in my intitial flow?

Thanks in advance!

NullPointerException processing disconnect

We are sometimes getting the following stack trace if we turn off bluetooth while communicating with a device:

no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.nextRequest(boolean)' on a null object reference
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.access$1300(BleManager.java:2071)
        at no.nordicsemi.android.ble.BleManager.internalDisconnect(BleManager.java:869)
        at no.nordicsemi.android.ble.BleManager.onRequestTimeout(BleManager.java:2056)
        at no.nordicsemi.android.ble.TimeoutableRequest.lambda$notifyStarted$0(TimeoutableRequest.java:188)
        at no.nordicsemi.android.ble.-$$Lambda$TimeoutableRequest$LRW3H3z9m1CuZHgzj67Qxd_-s8Y.run(lambda)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6816)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1563)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1451)

autoConnect=true attempts to reconnect even after invoking disconnect()

I'm trying to disconnect from a device with a connection attempt in progress, but apparently the disconnect is never executed (I never receive any callback) and the autoConnect=true causes an undesired reconnect attempt

Steps

  1. Invoke connect.await() on a switched off device
  2. After some seconds, invoke
        disconnect()
                .done { Timber.d("disconnect success") }
                .fail { device, status ->
                    Timber.d("disconnect fail")

                    close()
                }
                .enqueue()
  1. After some time, connect.await() throws a RequestFailedException: Request failed with status 133 and immediately attempts to reconnect. None of the disconnect callbacks is invoked

Is this working as intended or is it a bug?

createBond returning twice

Hello,

I'm using we are using your library for managing my BT connections and mostly it is working great. But I seem to run into some problems with the bonding process. It seems like the enqueue gets two callbacks, done and fail.

In short what happens is, I connect, create a bond, get success (done). I then disconnect and remove the bond and receive a fail.

I added a random number to log to just clarify I'm not calling the function twice.

D/RxBt: createBond 0.6858416588166597
I/BluetoothDevice: createBond() for device 91:3 called by pid: 623 tid: 623
E/RxBt: Bonding required
E/RxBt: Bonded!
D/RxBt: Already Bond success 0.6858416588166597
D/BluetoothDevice: bond, retrieved method: public boolean android.bluetooth.BluetoothDevice.removeBond()
I/BluetoothDevice: removeBond() for device 91:3 called by pid: 623 tid: 623
D/RxBt: Already Bond Fail 0.6858416588166597

Integrate with the Bond Management Service

Great to see all this code in a separate repo! I'll be migrating to it ASAP.

One feature request though: it would be great to see some integration with the bond management service so that I can request the deletion of the current bond with deleteBond() or some such method.

Opening API

Hi,
As you may have seen, most of the methods in the BleManager are package protected and final. My intention was to allow the final user to define the their manager's API without bringing all other methods with it. For example, the MySuperCoolManager extends BleManager would have a method enableFancyLED(), bond(), etc. and internal methods, like writeNotification would not be visible from outside. There are 2 methods exposed: connect(..) and disconnect(..), but not more.
The question is: is it a good idea, or does it make more troubles than good?
There are 3 solutions:

  1. It's good as it is. Package protected and final.
  2. All should be made public or at least not final.
  3. I may also expose some methods, like reading RSSI or bonding only.

As I'm thinking now, making them non-final is the best idea. Some methods could be made public by overriding them without actually changing functionality.

CC: @eliotstock, @maragues-kolibree, @sztomek, @balazsnemeth, @balazsnemeth, ...

ConnectRequest with autoConnect=true does not attempt to reconnect after timeout

Version: Beta5
Scenario
Attempt to connect to an offline device. After the connection attempt times out, switch the device on

bleManager.connect(bluetoothDevice)
      .useAutoConnect(true)
      .retry(3, 600)
      .enqueue();

Expected
The connection is attempted after the timeout

Got
The connection is never attempted after the timeout

Logs

13:58:41 BluetoothGatt: connect() - device: C0:4B:24:4B:11:A7, auto: false
13:58:41 BluetoothGatt: registerApp()
13:58:41 BluetoothGatt: registerApp() - UUID=1cc136ae-1d6f-4633-894a-5cf88ce20c60
13:58:41 BluetoothGatt: onClientRegistered() - status=0 clientIf=7

13:58:41 MyBleManagerCallback: onDeviceConnecting: C0:4B:24:4B:11:A7

13:59:12 BluetoothGatt: onClientConnectionState() - status=133 clientIf=7 device=C0:4B:24:4B:11:A7
13:59:12 BluetoothGatt: close()
13:59:12 BluetoothGatt: unregisterApp() - mClientIf=7

13:59:12 MyBleManagerCallback: onDeviceDisconnected: C0:4B:24:4B:11:A7
13:59:12 MyBleManagerCallback: onError: a BLE error has occurred message = Error on connection state change, code = 133

Related #31 (comment)

Add WaitForDisconnectRequest

This task would be useful to ensure that the device gets disconnected.

Story:

Calling gatt.disconnect() only closes the virtual connection associated with BluetoothGatt object. If there is another app connected to the same device, or the connection was opened multiple times in the application, the device will remain connected. The solution, to ensure disconnection, may be to implement a Disconnect Op Code on some Control Point characteristic on the remote device and then send this Op Code from the mobile phone.

Task:

Add a new request that will complete when the phone gets disconnected without calling gatt.disconnect().

API to set GAP event length

Hi,

I was running Nordic ATT MTU throughput test on nRF52840 between two boards. The test comes with SDK.

I want to do similar test with phone and nRF52840. I am using this library in my app. I can make connection to Nordic board which runs ATT MTU throughput. I have Samsung S9 which has BT5. I can see that 2MBPS phy is set. But it looks like there is no interface in this library to set GAP event length.

NRF_SDH_BLE_GAP_EVENT_LENGTH - GAP event length
The time set aside for this connection on every connection interval in 1.25 ms units.

Can you tell how to set this parameter from this android library ?

Also it looks like characteristic write is not synchronous. It means those are queued up. Is there any interface which does synchronous writes ?

Thanks,
Rahul

Users unbind the BLE from Android Setting Page with UART

Hi,
I unbind the BLE device from android setting page after the BLE device have connected with a correct bonding request.
Then I get Authentication required (5).
I need to restart the app to reconnect the BLE device.It will have correct behavior like normal use.

APP: nRF Toolbox (in develop branch)
Android-BLE-Library version : 2.0-alpha5
Phone: HTC Desire 820u with android 6.0.1
TEST BLE Device situation: the device send the bond request when we enable the TXCharacteristic notification.

nRF Toolbox UART, 2018-08-02
OTOHTR (E3:F8:E0:1C:61:39)
D 10:06:56.404 Creating service...
D 10:06:56.419 Binding to the service...
I 10:06:56.489 Service started
V 10:06:56.506 Connecting...
D 10:06:56.510 gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE)
D 10:06:56.549 Activity bound to the service
D 10:06:57.073 [Callback] Connection state changed with status: 0 and new state: 2 (CONNECTED)
I 10:06:57.078 Connected to E3:F8:E0:1C:61:39
D 10:06:57.085 wait(300)
V 10:06:57.400 Discovering services...
D 10:06:57.406 gatt.discoverServices()
I 10:06:57.436 Services discovered
V 10:06:57.441 Primary service found
V 10:06:57.547 Requesting new MTU...
D 10:06:57.550 gatt.requestMtu(260)
I 10:06:57.654 MTU changed to: 23
D 10:06:57.657 gatt.setCharacteristicNotification(6e400003-b5a3-f393-e0a9-e50e24dcca9e, true)
V 10:06:57.662 Enabling notifications for 6e400003-b5a3-f393-e0a9-e50e24dcca9e
D 10:06:57.665 gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
D 10:06:58.421 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D 10:06:58.526 [Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PASSKEY_CONFIRMATION (2)
D 10:07:06.536 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12)
I 10:07:06.543 Device bonded
D 10:07:06.549 gatt.setCharacteristicNotification(6e400003-b5a3-f393-e0a9-e50e24dcca9e, true)
V 10:07:06.556 Enabling notifications for 6e400003-b5a3-f393-e0a9-e50e24dcca9e
D 10:07:06.560 gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
I 10:07:06.668 Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
A 10:07:06.672 Notifications enabled
D 10:07:13.888 Activity unbound from the service
D 10:07:16.520 [Callback] Connection state changed with status: 22 and new state: 0 (DISCONNECTED)
W 10:07:16.527 Error: (0x16): GATT CONN TERMINATE LOCAL HOST
W 10:07:16.533 Connection lost
V 10:07:16.543 Connecting...
D 10:07:16.548 gatt.connect()
D 10:07:16.574 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
D 10:07:17.691 [Callback] Connection state changed with status: 0 and new state: 2 (CONNECTED)
I 10:07:17.697 Connected to E3:F8:E0:1C:61:39
D 10:07:17.705 wait(300)
V 10:07:18.012 Discovering services...
D 10:07:18.017 gatt.discoverServices()
I 10:07:18.029 Services discovered
V 10:07:18.033 Primary service found
V 10:07:18.038 Requesting new MTU...
D 10:07:18.042 gatt.requestMtu(260)
I 10:07:18.166 MTU changed to: 23
D 10:07:18.170 gatt.setCharacteristicNotification(6e400003-b5a3-f393-e0a9-e50e24dcca9e, true)
V 10:07:18.175 Enabling notifications for 6e400003-b5a3-f393-e0a9-e50e24dcca9e
D 10:07:18.179 gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
D 10:07:18.714 [Callback] Connection state changed with status: 19 and new state: 0 (DISCONNECTED)
W 10:07:18.730 Error: (0x13): GATT CONN TERMINATE PEER USER
W 10:07:18.736 Connection lost
D 10:07:18.875 Activity bound to the service
D 10:07:43.007 [Callback] Connection state changed with status: 0 and new state: 2 (CONNECTED)
I 10:07:43.018 Connected to E3:F8:E0:1C:61:39
D 10:07:43.024 wait(300)
V 10:07:43.330 Discovering services...
D 10:07:43.334 gatt.discoverServices()
I 10:07:43.347 Services discovered
V 10:07:43.352 Primary service found
V 10:07:43.456 Requesting new MTU...
D 10:07:43.460 gatt.requestMtu(260)
I 10:07:43.589 MTU changed to: 23
D 10:07:43.595 gatt.setCharacteristicNotification(6e400003-b5a3-f393-e0a9-e50e24dcca9e, true)
V 10:07:43.600 Enabling notifications for 6e400003-b5a3-f393-e0a9-e50e24dcca9e
D 10:07:43.604 gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
W 10:07:43.701 Authentication required (5)

Build fail due to Invoke-customs are only supported starting with Android O (--min-api 26)

I got the following build error after using Android-BLE-Library

Invoke-customs are only supported starting with Android O (--min-api 26)
Message{kind=ERROR, text=Invoke-customs are only supported starting with Android O (--min-api 26), sources=[Unknown source file], tool name=Optional.of(D8)}

Then I change the Source Compatibility and Target Compatibility to 1.8 as suggested from the Internet

compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

and got the following error

Process 'command '/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java'' finished with non-zero exit value 1

Does Android-BLE-Library require a certain minSdkVersion? My project has minSdkVersion 19

Null pointer exception while turning off bluetooth.

@philips77
Version : v2.0 alpha 5
I am using the Profile Service Ready Activity in the nRF Toolbox/develop project. Everything is working as excepted but when I disconnect the bluetooth I am getting this error. Auto connect is turned off and also service is stopped after disconnect.

java.lang.NullPointerException: Attempt to invoke virtual method 'void no.nordicsemi.android.ble.WriteRequest.notifyPacketSent(android.bluetooth.BluetoothDevice, byte[])' on a null object reference
at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.onCharacteristicWriteSafe(BleManager.java:2348)
at no.nordicsemi.android.ble.MainThreadBluetoothGattCallback.lambda$onCharacteristicWrite$3$MainThreadBluetoothGattCallback(MainThreadBluetoothGattCallback.java:119)
at no.nordicsemi.android.ble.MainThreadBluetoothGattCallback$$Lambda$3.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6269)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)

ClassCastException: Bootstrap method returned null

When using beta6, trying to connect to a device from the onScanResult() method in the scan callback as follows:

    BleDeviceManager bleDeviceManager = BleDeviceManager.getInstance(context.getApplicationContext());

    BleDevice2 device = new BleDevice2();
    bleDeviceManager.setGattCallbacks(device);

    try {
        bleDeviceManager.connect(result.getDevice())
                .retry(3, 100)
                .useAutoConnect(false)
                .enqueue();
    }
    catch (Exception e) {
        Logg.e(TAG, "Can't connect to device: " + e.getMessage());
    }

I get the following stack trace:

2018-10-26 17:06:47.480 20222-20222/cc.biketracker.android I/BleScanCallback: Scan result: Device name: 00228892, address: C7:56:60:F0:56:58, RSSI: -59
2018-10-26 17:06:47.493 20222-20222/cc.biketracker.android D/BleScanCallback: Bond state: BOND_BONDED
2018-10-26 17:06:47.498 20222-20222/cc.biketracker.android D/BleScanCallback: Found device. Stopping scanning.
2018-10-26 17:06:47.503 20222-20222/cc.biketracker.android D/BluetoothAdapter: isLeEnabled(): ON
2018-10-26 17:06:47.543 20222-20222/cc.biketracker.android D/AndroidRuntime: Shutting down VM
2018-10-26 17:06:47.558 20222-20222/cc.biketracker.android E/AndroidRuntime: FATAL EXCEPTION: main
    Process: cc.biketracker.android, PID: 20222
    java.lang.BootstrapMethodError: Exception from call site #9 bootstrap method
        at no.nordicsemi.android.ble.BleManager.enqueue(BleManager.java:1860)
        at no.nordicsemi.android.ble.Request.enqueue(Request.java:751)
        at cc.biketracker.android.ble.BleScanCallback.onScanResult(BleScanCallback.java:173)
        at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:484)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6680)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.ClassCastException: Bootstrap method returned null
        at no.nordicsemi.android.ble.BleManager.enqueue(BleManager.java:1860)ย 
        at no.nordicsemi.android.ble.Request.enqueue(Request.java:751)ย 
        at cc.biketracker.android.ble.BleScanCallback.onScanResult(BleScanCallback.java:173)ย 
        at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:484)ย 
        at android.os.Handler.handleCallback(Handler.java:873)ย 
        at android.os.Handler.dispatchMessage(Handler.java:99)ย 
        at android.os.Looper.loop(Looper.java:193)ย 
        at android.app.ActivityThread.main(ActivityThread.java:6680)ย 
        at java.lang.reflect.Method.invoke(Native Method)ย 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)ย 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)ย 
2018-10-26 17:06:47.565 20222-20222/cc.biketracker.android E/UncaughtException: java.lang.BootstrapMethodError: Exception from call site #9 bootstrap method
        at no.nordicsemi.android.ble.BleManager.enqueue(BleManager.java:1860)
        at no.nordicsemi.android.ble.Request.enqueue(Request.java:751)
        at cc.biketracker.android.ble.BleScanCallback.onScanResult(BleScanCallback.java:173)
        at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:484)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6680)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.ClassCastException: Bootstrap method returned null
        at no.nordicsemi.android.ble.BleManager.enqueue(BleManager.java:1860)ย 
        at no.nordicsemi.android.ble.Request.enqueue(Request.java:751)ย 
        at cc.biketracker.android.ble.BleScanCallback.onScanResult(BleScanCallback.java:173)ย 
        at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:484)ย 
        at android.os.Handler.handleCallback(Handler.java:873)ย 
        at android.os.Handler.dispatchMessage(Handler.java:99)ย 
        at android.os.Looper.loop(Looper.java:193)ย 
        at android.app.ActivityThread.main(ActivityThread.java:6680)ย 
        at java.lang.reflect.Method.invoke(Native Method)ย 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)ย 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)ย 

It could be I'm using the API incorrectly. It seems strange that this is supposed to happen on the UI thread, given I'm scanning in the background from a service. I did try using await() rather than enqueue, but that failed with another exception indicating I should be using enqueue().

Can't send 2 packages

Hi, I send 2 packages but after the first package, flag mOperationInProgress became true and when I send the second package, package doesn't sending because mOperationInProgress == true. How I can fix it?

Version of library: 1.2.0

Bonding at initialize() or reading Char that requires bond

Hello again!

Thanks for you last fix, it solved my issue. :) I've ran into another strange case. Let's say you want to connect to a device and bond that device. What is the flow for this? I've tried several different ways but ran into different issues.

  • enqueue a bond in the initialization?
/** BleManagerGattCallback **/
        override fun initialize() {
            super.initialize()
            createBond().enqueue()
            readCharacteristic(bondCharacteristics).with(bondDataCallback).enqueue()            
            readCharacteristic(modeCharacteristics).with(modeCallback).enqueue()
            setNotificationCallback(modeCharacteristics).with(modeCallback)

        }
        ...

In the case above everything below createBond() will be ignored.

  • read a characteristic that require bonding, and handle onBondingRequired?
        override fun initialize() {
            super.initialize()
            readCharacteristic(bondCharacteristics).with(bondDataCallback).enqueue()           
        }
        ...

In this case I get:

E/BleManager: onCharacteristicRead error 8

It does not seem to match the BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION, see https://github.com/NordicSemiconductor/Android-BLE-Library/blob/master/ble/src/main/java/no/nordicsemi/android/ble/BleManager.java#L1316
However, it will log in the nRF Logger: Error (0x8): GATT INSUF AUTHORIZATION.

Or is the right way to go to create a bond after connect done callback and then do additional reading for characteristics that require bond?

[beta6] NPE invoking mGattCallback.nextRequest

I received a crash stacktrace that points to BleManager.enqueue

	protected final void enqueue(@NonNull final Request request) {
		if (mGattCallback == null) {
			mGattCallback = getGattCallback();
		}
		// Add the new task to the end of the queue.
		mGattCallback.enqueue(request);
		runOnUiThread(() -> mGattCallback.nextRequest(false)); <-- NPE
	}

When executing that Runnable, mGattCallback is null. It obviously wasn't null in the line above, which means we nullified the gattCallback instance. If I'm not mistaken, this can only happen due to a close invocation.

The easiest way is to add a null check on mGattCallback after locking mLock. If you are fine with this solution, I can create the PR, but you may want to analyze if there are other consequences.

Suggestion - Retry the operation that triggered bonding but failed

Reading an encrypted characteristic will trigger the bonding process to start. However, the read/write that triggered it sometimes fails. I see this happening a lot on Android 6 and far less on 7 & 8. When it happens I get a GATT_AUTH_FAIL (error 137) and I re-try the operation which then always succeeds.

It seems that on later Android versions (7 & 8), the stack retries the operation itself. I don't have proof for it other than I don't see any read/write failed errors on those Android versions.

So my suggestion would be to add an extra check and to retry the operation that triggered the bonding process. That way the users of the BleManager don't have to worry about it. Here is what I do:

public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            // Perform some checks on the status field
            if(status!= GATT_SUCCESS) {
                if (status == GATT_AUTH_FAIL) {
                    // Characteristic encrypted and needs bonding, so retry operation
                    // This only seems to happen on Android 6
                    HBLogger.v(TAG, "Write failed (Authentication failed), bonding in progress so retrying write command");
                    retryCommand();
                    return;
                } else if (status == GATT_INSUFFICIENT_AUTHENTICATION) {
                    // Characteristic encrypted and needs bonding, so retry operation
                    // This only seems to happen on Android < 6
                    HBLogger.v(TAG, "Write failed (Insufficient authentication), bonding in progress so retrying write command");
                    retryCommand();
                    return;
                }
...

Same thing is done in onCharacteristicRead of course....

Galaxy S9 won't disconnect from device

I am hoping to find a work around on a BLE bug using the BleManager and the GS9.

I find after a few connect/disconnect cycles that the peripheral device remains connected.

The almost unbelievable part is that toggling the BT icon on the phone does not disconnect the device. When I restart the GS9 I can then see the device disconnect.

Perhaps you might have a more reliable way I should be disconnecting where I call disconnect() and wait for a callback to ensure the device really disconnected?

Getting Android to generate LL_LENGTH_REQ, to extend PDU

Hi,

I'm trying to use the library to get communication between an Android mobile and a BLE peripheral
which utilises the extended PDU.

To understand things I wrote the central using the Nordic SDK 15.x. With the Nordic central I found it was
necessary to get the central to send a LL_LENGTH_REQ, to get the peripheral to extend the length of
the PDU. This was required in addition to the request to increase the MTU size.

Does the library support making such a request from an Android device?

Is it possible to make this request from and Android device?

I'm not certain whether this is the real problem, as there seems to be discussion about
Android transparently chunking characteristics over 20 bytes length. Is it also necessary
to tell Android not to employ this mechanism, to ensure it utilises the full PDU
once its enabled?

I'm noticing that currently extended length notification is being transferred in fragments.

Again is the control of the chunking within Android something the library supports?

Grateful for any help you can provide on this matter!

connectGatt Handler

First of all, thank you for a great library. In our app we provide the ability to download the firmware from our device. We do this be sending a certain command and the device will consistently send back a batch of packets until the firmware has been fully received. We verify each batch using a checksum to ensure it's correct when receiving it. We recently switched to this library and noticed that the functionality was broken as it would send back packets that didn't make sense (the data was different on every request, the number of packets were erratic and the checksum values never validated). After many hours debugging I found that it all related back to the connectGatt method in the BleManager.java file.

This was tested on a Samsung Galaxy S9+.

This causes the issue:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        ...
        mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback,
                             BluetoothDevice.TRANSPORT_LE, preferredPhy, mHandler);
}

However, this fixes the issue:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        ...
        mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback,
                             BluetoothDevice.TRANSPORT_LE, preferredPhy); //, mHandler);
}

For now we will have to keep the module in our project to ensure it works across multiple devices, but it would be nice to pull this out and just use Gradle.

Appreciate it.

[EDIT] - The code didn't save correctly. Essentially I commented out the mHandler in the connectGatt method.

getGattCallback null object

Hi,

I've had 2 of my users recently crash with the following null object crash on beta5 version of the library. I'm unsure what exactly is happening at the moment in time before it crashes as I've never seen this on my devices, but wanted to share it in case there is something obvious you can spot?
I have several hundred other users all using the app (and library) without problem, so don't think this is a huge problem.

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void no.nordicsemi.android.ble.a$a.a(android.os.Handler)' on a null object reference
       at no.nordicsemi.android.ble.BleManager.getGattCallback(BleManager.java:680)
       at no.nordicsemi.android.ble.BleManager.getGattCallback(BleManager.java:114)
       at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.lambda$onConnectionStateChangeSafe$1(BleManager.java:2237)
       at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.lambda$hHV_dPbGJHyD-KM5FND5GY7KZA0(Unknown Source)
       at no.nordicsemi.android.ble.-$$Lambda$a$a$hHV_dPbGJHyD-KM5FND5GY7KZA0.run(Unknown Source:4)
       at android.os.Handler.handleCallback(Handler.java:789)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6944)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

How to send more than 20 bytes of data with 1.2.0 ?

Hi,

I need to send/receive more than 20 bytes of data through BLE. I read #3 for sending more than 20 bytes. However I would like to use Android-BLE-Library 1.2.0 for some reason. Could you let me know where to modify in 1.2.0 ?

Anyway did you try all 3 approaches in #3 at Android-BLE-Library 2..?

Thanks.

[Beta6] NoSuchElementException (Nexus 4 only)

Device: Nexus 4 running 5.1.1

    java.util.NoSuchElementException
        at java.util.LinkedList.removeFirstImpl(LinkedList.java:689)
        at java.util.LinkedList.removeFirst(LinkedList.java:676)
        at java.util.LinkedList.poll(LinkedList.java:895)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.nextRequest(BleManager.java:2864)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.onCharacteristicWriteSafe(BleManager.java:2482)
        at no.nordicsemi.android.ble.MainThreadBluetoothGattCallback.lambda$onCharacteristicWrite$3(MainThreadBluetoothGattCallback.java:128)
        at no.nordicsemi.android.ble.-$$Lambda$MainThreadBluetoothGattCallback$dAnXisth7CAlJFFhbDJ5X_192I0.run(lambda)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)```

autoConnect stopped working since graduating from pre v1.0 to 1.2

Hi,

My app connects to a sensor which occasionally (after 30 seconds of no use) switches off. When switched off, the phone should continue to try to reconnect to it, so that the moment the sensor turns back on it seamlessly reconnects.

I have had this app released (with >200 users) for some time using the version before it was released on Maven. This behaviour has been working perfectly with the old version of this library.

Since upgrading to V1.2 over the weekend, my app no longer reconnects (I have confirmed that the sensor is actually turned on).
It looks like the initial connection using autoConnect = false works perfectly, but after the sensor has then turned off, and back on again (so now connecting with autoConnect = true), no connection is made. I have made no changes since upgrading to V1.2 (except importing the new Request class) - am I doing anything wrong?

I have NRFLogger running with some debug messages on the BLEManager callbacks. A typical debug output looks something like this:

onDeviceConnecting
gatt=device.connectGatt(autoConnect = false)
onDeviceConnected
onServicesDiscovered
Notifications Enabled
onDeviceReady
Notification Received 
... (lots of notification received - 1 every second. This is normal usage)
Notification Received 
Connection state changed with status : 8 and new state: 0 (DISCONNECTED)
Error: (0x8): GATT CONN TIMEOUT (this is expected - the sensor has gone to sleep now)
Connection Lost
onLinkLossOccur
onDeviceConnecting
gatt.connect()
(at this point the sensor is turned on, advertising and available for connection - but app doesn't connect)

Currently this version of my app has not been released, and has only been tested on my Pixel 2 development phone - but seems consistent behaviour.

Parameter specified as non-null is null

The request that fails is

fun disconnectWithoutReconnect() {
        disconnect()
                .done { Timber.d("disconnect success") }
                .fail { device, status ->
                    Timber.d("disconnect fail")

                    close()
                }
                .enqueue()
    }
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter it
        at com.mycompany.MyNordicBleManager$disconnectWithoutReconnect$1.onRequestCompleted(Unknown Source:2)
        at no.nordicsemi.android.ble.Request.notifySuccess(Request.java:829)
        at no.nordicsemi.android.ble.BleManager.internalDisconnect(BleManager.java:665)
        at no.nordicsemi.android.ble.BleManager.access$2100(BleManager.java:113)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.nextRequest(BleManager.java:2812)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.access$1300(BleManager.java:1812)
        at no.nordicsemi.android.ble.BleManager.lambda$enqueue$4(BleManager.java:1786)
        at no.nordicsemi.android.ble.-$$Lambda$BleManager$KDSxdgn5nClZRFe_FvyLUfX8mWc.run(Unknown Source:2)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Scenario

  • beta2
  • attempt to disconnect from a device I'm not connected to. In this case, I never even attempted to connect to it.

[Beta3] NPE BleManager$BleManagerGattCallback.nextRequest(boolean)' on a null object reference

On Beta3, it happened after I tried to connect and received a TimeoutException

Process: com.mycompany, PID: 20828
    java.lang.NullPointerException: Attempt to invoke direct method 'void no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.nextRequest(boolean)' on a null object reference
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.access$1300(BleManager.java:1836)
        at no.nordicsemi.android.ble.BleManager.lambda$enqueue$4(BleManager.java:1804)
        at no.nordicsemi.android.ble.-$$Lambda$BleManager$KDSxdgn5nClZRFe_FvyLUfX8mWc.run(Unknown Source:2)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

Might it be that I immediately tried to connect again, even before receiving bluetoothgatt close callback?

//Exception stack trace
2018-10-01 14:51:21.872  D/MyClass: Invoking connect 
2018-10-01 14:51:21.873  D/BluetoothGatt: close()
2018-10-01 14:51:21.873  D/BluetoothGatt: unregisterApp() - mClientIf=7
2018-10-01 14:51:21.881  D/MyClass: onError: a BLE error has occurred message = Error on connection state change, code = 133

Enqueueing request in onDeviceDisconnected causes problems

When a connection is disconnected by remote side (status 8), and the manager calls notifyDeviceDisconnected(), it first calls close(), then onDeviceDisconnected().
If a new connection request was added in onDeviceDisconnected() is will be proceeded immediately, as the mOperationInProgress` flag was cleared.
The new request fail callback would be invoked a moment later with the old's request status (8).

Question about delay when calling discoverServices for bonded devices

I saw you recently added a delay in onConnectionStateChange before calling discoverServices for bonded devices. I also observed the need for this during testing with several devices so this is definately needed in some cases!

I have a couple of questions:

  • I only have a limited set of devices and phones at my disposal and I only observed this issue on Android 6. On Android 7 & 8 the delay doesn't seem necessary. Your code doesn't look at the Android version but I think this is only needed for Android < 7. Did you also observe the need for a delay on Android 7 & 8?

  • You use a 1600 ms delay. The device I encountered that needed a delay was the A&D UA-651BLE and with that one 600 ms seemed enough. Why are you suggesting 1600 ms? Seems quite long...

  • What is your theory about why the delay is needed? My guess is that Android is doing the key exchange with the bonded peripheral and service discovery cannot be started until this has finished. I don't know enough about low-level Bluetooth to be sure...

Necessity to compile for VERSION_1_8

It might be worth adding to the instructions to use this, the need for adding

+    compileOptions {
+        targetCompatibility JavaVersion.VERSION_1_8
+        sourceCompatibility JavaVersion.VERSION_1_8
+    }

to the gradle files for all the modules that include this. I was getting a fairly cryptic error
code com.android.dx.cf.code.SimException: invalid opcode ba (invokedynamic requires --min-sdk-version >= 26)
that I eventually tracked down to this. Alternatively, I'm not sure how necessary the lambda
expression in BleManager is since without that this restriction might not be required.

Crash when initializing a weak connection

When my device is just on the edge of range and ultimately probably won't establish a reliable connection I get this error stack from the Android-BLE-Library:

04-12 16:53:03.586 8991-9590/org.sralab.emgimu W/BluetoothGatt: Unhandled exception in callback
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.bluetooth.BluetoothDevice android.bluetooth.BluetoothGatt.getDevice()' on a null object reference
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.onDeviceReady(BleManager.java:1276)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.nextRequest(BleManager.java:1734)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.nextRequest(BleManager.java:1834)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.nextRequest(BleManager.java:1834)
        at no.nordicsemi.android.ble.BleManager$BleManagerGattCallback.onCharacteristicRead(BleManager.java:1550)
        at android.bluetooth.BluetoothGatt$1$6.run(BluetoothGatt.java:364)
        at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:725)
        at android.bluetooth.BluetoothGatt.-wrap0(Unknown Source:0)
        at android.bluetooth.BluetoothGatt$1.onCharacteristicRead(BluetoothGatt.java:358)
        at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:124)
        at android.os.Binder.execTransact(Binder.java:697)

In my case I get a link loss callback so I close the BleManager. This sets the GattCallback to null. It seems like when the BleManager is in this state, it should not attempt to go through the initialization requests.

Wrong NonNull annotations in response package

All getters in response package are annotated with NonNull, when truth is that that's not guaranteed.

In fact, in the past I have received WriteResponse's with rawData null. I think they were caused by #48, but still, it's possible

I created a PR to change annotations to Nullable
#49

I'm having CLA signing issues, I'll look into that later.

Improve testability

Given the current code, we are very limited on how much we can test our BleManager descendants.

  • We can't unit test it because the constructor initializes a Handler from the main looper, so we are forced to use AndroidJUnit4 runner
  • When running on AndroidJUnit4, Mockito can't mock final classes. I'd like to not include PowerMock, but I may end up doing that.
    • We can't test our BleManagerGattCallback, which receives BluetoothGatt as a parameter. And we can't move the implementation to an independent class because we have to fetch & store the GattCharacteristics to be used later
    • We can't test our bluetooth operations, which throw InvalidRequestException because mBluetoothDevice is null. And that's probably only the tip of the iceberg, I haven't gone past that point.

Making the code testable would be a daunting task, but maybe we could start with something simple such as exposing a constructor that takes a Handler as parameter. There's a VisibleForTesting annotation that will flag the usage as a lint error if used outside from test sourceset. VisibleForTesting lives in an independent package (com.android.support:support-annotations:XXX, maybe it's androidx now?)

I'm eager to listen to other ideas, I'm sure I'm not the only one having this issue.

Thanks!

[v2.0.0] ConnectionRequest.useAutoConnect flag is ignored

Hi @philips77,

I just noticed that the autoConnect flag is always passed with false value to BluetoothDevice.connectGatt(Context, boolean, BleManagerGattCallback) in the BleManager.internalConnect method.
Because of this, android won't try to connect automatically to a previously connected (and paired in my case) device when it comes online.

Could you please have a look on this issue?

Thanks in advance, cheers!

Disable notifications ACK not received, trying to enable notifications throws Status -3

One of the operations I perform often is an atomic enable/disable notifications and write characteristic

        Timber.d("$rawDataOn pre")
beginAtomicRequestQueue()
            .add(klEnableNotificationsRequest(sensorsRawDataCharacteristic, rawDataOn)) //enables/disables notifications
            .add(writeCharacteristic(sensorsStreamingControlCharacteristic, payload))
            .before {
                Timber.d("$rawDataOn before")
            }
            .done {
                Timber.d("$rawDataOn Completed")
            }
            .enqueue()

A standard execution when passing "false" logs something like this

12:13:20.565 false pre
12:13:20.565 false before
12:13:20.566 gatt.setCharacteristicNotification(01000001-55d0-4989-b640-cfb64e5c34e0, false)
12:13:20.566 setCharacteristicNotification() - uuid: 01000001-55d0-4989-b640-cfb64e5c34e0 enable: false
12:13:20.567 Disabling notifications and indications for 01000001-55d0-4989-b640-cfb64e5c34e0
12:13:20.568 gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x00-00)
12:13:20.575 Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 00-00
12:13:20.575 Notifications and indications disabled
12:13:20.576 Writing characteristic 04000001-55d0-4989-b640-cfb64e5c34e0 (WRITE REQUEST)
12:13:20.576 gatt.writeCharacteristic(04000001-55d0-4989-b640-cfb64e5c34e0)
12:13:20.577 false Completed

Some times, if there are consecutive calls with enable set to false and then true, it tries to enable notifications before the disable is complete. Apparently, the "disable notifications" request never confirms that the notifications are disabled but still completes

12:13:19.467 false pre
12:13:19.495 true pre
12:13:20.485 false before
12:13:20.486 gatt.setCharacteristicNotification(01000001-55d0-4989-b640-cfb64e5c34e0, false)
12:13:20.486 setCharacteristicNotification() - uuid: 01000001-55d0-4989-b640-cfb64e5c34e0 enable: false
12:13:20.489 Disabling notifications and indications for 01000001-55d0-4989-b640-cfb64e5c34e0
12:13:20.490 gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x00-00)
12:13:20.504 Writing characteristic 04000001-55d0-4989-b640-cfb64e5c34e0 (WRITE REQUEST)
12:13:20.505 gatt.writeCharacteristic(04000001-55d0-4989-b640-cfb64e5c34e0)
12:13:20.507 false Completed
12:13:20.508 true before
12:13:20.510 klEnableNotificationsRequest setNotificationCallback
12:13:20.511 gatt.setCharacteristicNotification(01000001-55d0-4989-b640-cfb64e5c34e0, true)
12:13:20.511 setCharacteristicNotification() - uuid: 01000001-55d0-4989-b640-cfb64e5c34e0 enable: true
12:13:20.514 Enabling notifications for 01000001-55d0-4989-b640-cfb64e5c34e0
12:13:20.514 gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
-> error -3 12:13:20.516 Failed to enabled notifications for 01000001-55d0-4989-b640-cfb64e5c34e0 (status = -3)
12:13:20.517 Writing characteristic 04000001-55d0-4989-b640-cfb64e5c34e0 (WRITE REQUEST)
12:13:20.518 gatt.writeCharacteristic(04000001-55d0-4989-b640-cfb64e5c34e0)
12:13:20.519 true Completed

If you compare it with the previous log, it's missing the "disable notifications" ACK

12:13:20.575 Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 00-00
12:13:20.575 Notifications and indications disabled

Does it sound like a bug in the library?

We develop our own firmware so there might as well be a bug there, but I don't have a sniffer to check the packets.

Callback onConnectionStateChange after disconnect can put BleManager in inconsistent state

I am seeing a situation where onConnectionStateChangeSafe in BleManager gets called with newState == BluetoothProfile.STATE_CONNECTED after I do a disconnect (call BleManager.disconnect()).

This causes mConnected to be set to true, but mBluetoothDevice is null. This makes both connect do nothing (since mConnected is true) and disconnect to nothing (since mBluetoothDevice is null), so the BleManager is no longer of much use.

Some more rough details on what I'm doing:

  1. Connecting (calling BleManager.connect()).
  2. Enabling notifications for a couple of characteristics. Reading and writing some characteristics.
  3. Disconnecting.
  4. Repeat.

This is not done in quick succession - between the disconnect and the next connect for instance there is a pause several seconds long.

This works fine most of the time, but sometimes, there is a call to onConnectionStateChangeSafe after the disconnect, which causes the problem described above.

Side note: The purpose for this is to implement a communications protocol where characteristics are used to transfer data, and the error handling is specified as disconnecting, reconnecting, and starting over.

I have been using version 2.0-beta10.

Device disconnects automatically inmediately after connection

Hi all,

I am facing some connection problems with the library. I downloaded it 4 days ago and yesterday I started calling the BLEManager connect(device) method. All devices are correctly scanned but when I start the connection, I can connect to the device but immediately it disconnects from the device. I have no clue about what can be causing this problem. Here is the trace I get from logcat:

D/TEST-LP: onDeviceConnecting: LUIS-05B6
D/BluetoothGatt: connect() - device: DB:AB:2A:56:B6:05, auto: false registerApp()
D/BluetoothGatt: registerApp() - UUID=282d31c8-d3d0-4969-88a7-b233d4c2babc
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=6
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=DB:AB:2A:56:B6:05
D/TEST-LP: onDeviceConnected: LUIS-05B6
D/BluetoothGatt: discoverServices() - device: DB:AB:2A:56:B6:05
D/BluetoothGatt: onConnectionUpdated() - Device=DB:AB:2A:56:B6:05 interval=6 latency=0 Timeout=500 status=0
D/BluetoothGatt: onSearchComplete() = Device=DB:AB:2A:56:B6:05 Status=0
D/BluetoothGatt: cancelOpen() - device: DB:AB:2A:56:B6:05
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=6 device=DB:AB:2A:56:B6:05
D/TEST-LP: onDeviceDisconnected: LUIS-05B6

If you want to see some part of the code just let me know. Any help is apreciated!

*Edit: logcat formatted

Data lost during sync using notifications

Hi,
I am using this library to connect to a sensor that's using characteristic notification to send data.
I enable the notifications and I am able to receive data but the data is getting lost somewhere between being received by Android device and being received in Gattcallbacks.
The sensor also uses a nordic processing unit and updates notification characteristic every 20ms.
No matter the size of data, BlinkyManager reports data size to be approx 8000 notification updates.

However, the data size can be up to 10 Mb and I can only receive less than 1 Mb.

Timeout on first connection and error 133

I can no longer reliably connect to a new peripheral. The connection times out after 30s and then I get error 133. Here's the logging on the Android side.

2018-11-30 16:04:14.048 11300-11300/? I/ProvisioningActivity: Device C7:56:60:F0:56:58 clicked.
2018-11-30 16:04:14.196 11300-11300/? D/ProvisioningActivity: Device 228892 exists and is unowned. Good.
2018-11-30 16:04:14.205 11300-11300/? I/ProvisioningActivity: Connecting to C7:56:60:F0:56:58
2018-11-30 16:04:14.214 11300-11300/? D/BikeTrackerManager: onDeviceConnecting()
2018-11-30 16:04:14.215 11300-11300/? D/BluetoothGatt: connect() - device: C7:56:60:F0:56:58, auto: false
2018-11-30 16:04:14.215 11300-11300/? D/BluetoothGatt: registerApp()
2018-11-30 16:04:14.215 11300-11300/? D/BluetoothGatt: registerApp() - UUID=f0f74613-fc8c-4347-bdd0-9baa346f1b46
2018-11-30 16:04:14.219 11300-11357/? D/BluetoothGatt: onClientRegistered() - status=0 clientIf=9
2018-11-30 16:04:17.485 11300-11300/? I/chatty: uid=10209(cc.biketracker.android) identical 2 lines
2018-11-30 16:04:44.231 11300-11357/? D/BluetoothGatt: onClientConnectionState() - status=133 clientIf=9 device=C7:56:60:F0:56:58
2018-11-30 16:04:44.237 11300-11300/? D/BluetoothGatt: close()
2018-11-30 16:04:44.237 11300-11300/? D/BluetoothGatt: unregisterApp() - mClientIf=9
2018-11-30 16:04:44.239 11300-11300/? D/BikeTrackerManager: onDeviceDisconnected()
2018-11-30 16:04:44.239 11300-11300/? D/ProvisioningActivity: Disconnected. Presenting alert dialog.
2018-11-30 16:04:44.332 11300-11307/? I/tracker.androi: Compiler allocated 4MB to compile void android.widget.TextView.<init>(android.content.Context, android.util.AttributeSet, int, int)
2018-11-30 16:04:44.341 11300-11300/? D/BikeTrackerManager: onDeviceDisconnected()
2018-11-30 16:04:44.359 11300-11300/? W/AudioTrack: Use of stream types is deprecated for operations other than volume control
2018-11-30 16:04:44.359 11300-11300/? W/AudioTrack: See the documentation of AudioTrack() for what to use instead with android.media.AudioAttributes to qualify your playback use case
2018-11-30 16:04:44.433 11300-11300/? W/AudioTrack: Use of stream types is deprecated for operations other than volume control
2018-11-30 16:04:44.433 11300-11300/? W/AudioTrack: See the documentation of AudioTrack() for what to use instead with android.media.AudioAttributes to qualify your playback use case
2018-11-30 16:04:44.622 11300-11300/? D/LocalBroadcastUtil: Local broadcast message: model changed.
2018-11-30 16:04:44.627 11300-11300/? D/BleBackgroundScanner: Bonded peripherals:
2018-11-30 16:04:44.629 11300-11300/? D/BleBackgroundScanner: No Bike Tracker devices bonded to this phone. Not scanning.
2018-11-30 16:04:44.630 11300-11300/? D/BikeTrackerManager: onError()
2018-11-30 16:04:44.630 11300-11300/? E/ProvisioningActivity: BLE error: 133: Error on connection state change

I'm connecting like this:

bleDeviceManager.connect(selectedBluetoothDevice.getDevice())
                    .retry(3, 200)
                    .useAutoConnect(false)
                    .enqueue();

On the device (peripheral) side, I don't get any logging for the connection at all. It's like nothing's happened on the radio. I don't have a sniffer dongle to hand to check for sure.

I first saw this on v2.0.0 and have just verified it on v2.0.2. I've been able to connect once, without having changed any code on either side, but then after clearing the bond on both sides and testing again, I can't connect. Turning off the Bluetooth adapter on the phone, rebooting the phone, reflashing the device - nothing seems to put it right. I can repro this with the DK as the peripheral, so it's not a hardware thing with my device.

I can also connect, and bond, from the nRF Connect app.

Happy to share both the device firmware and the Android app source code privately. Anything else I can check, until I get back to my sniffer and Wireshark?

Connection no longer possible after turning bluetooth off (when it is turned back on)

This was tested on the develop branch (v2 library - 2.0-alpha6) and everything seems to be working correctly in all cases, except for when bluetooth is disabled on the device (after connection has been made). When bluetooth is re-enabled, connection is no longer possible.

I have debugged it and it seems that the issue is related to mOperationInProgress flag in `BleManagerGattCallback'. When call for connection is made:

@Deprecated
protected final void enqueue(@NonNull final Request request) {
if (mGattCallback == null) {
mGattCallback = getGattCallback();
}
// Add the new task to the end of the queue.
mGattCallback.enqueue(request);
runOnUiThread(() -> mGattCallback.nextRequest(false));
}

flag is checked and call is silently skipped (none of the callbacks will be called in this case):

private void nextRequest(final boolean force) {
if (force) {
mOperationInProgress = mValueChangedRequest != null;
}
if (mOperationInProgress) {
return;
}

When bluetooth is disabled on device, broadcast receiver is called:

@Override
public void onReceive(final Context context, final Intent intent) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
final int previousState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BluetoothAdapter.STATE_OFF);
final String stateString = "[Broadcast] Action received: " + BluetoothAdapter.ACTION_STATE_CHANGED +
", state changed to " + state2String(state);
log(Level.DEBUG, stateString);
switch (state) {
case BluetoothAdapter.STATE_TURNING_OFF:
case BluetoothAdapter.STATE_OFF:
if (mConnected && previousState != BluetoothAdapter.STATE_TURNING_OFF
&& previousState != BluetoothAdapter.STATE_OFF) {
// No more calls are possible
mGattCallback.mOperationInProgress = true;
mGattCallback.cancelQueue();
mGattCallback.mInitQueue = null;
// Signal the current request, if any
if (mRequest != null && mRequest.type != Request.Type.DISCONNECT) {
mRequest.notifyFail(mBluetoothDevice, FailCallback.REASON_BLUETOOTH_DISABLED);
mRequest = null;
}
if (mValueChangedRequest != null) {
mValueChangedRequest.notifyFail(mBluetoothDevice, FailCallback.REASON_BLUETOOTH_DISABLED);
mValueChangedRequest = null;
}
if (mConnectRequest != null) {
mConnectRequest.notifyFail(mBluetoothDevice, FailCallback.REASON_BLUETOOTH_DISABLED);
mConnectRequest = null;
}
// The connection is killed by the system, no need to disconnect gently.
mUserDisconnected = true;
mGattCallback.notifyDeviceDisconnected(mBluetoothDevice);
}
// Calling close() will prevent the STATE_OFF event from being logged
// (this receiver will be unregistered). But it doesn't matter.
close();
break;
}
}

which then prevents all further calls by setting this flag.

// No more calls are possible
mGattCallback.mOperationInProgress = true;
mGattCallback.cancelQueue();
mGattCallback.mInitQueue = null;

I haven't seen it turned back to false to enable new connections.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.