@@ -62,13 +62,16 @@ public class BLEPair implements BluetoothAdapter.LeScanCallback {
62
62
// Android 13 - I have seen 4 status 133s before a good connect and pair
63
63
private int pairChecks = 0 ;
64
64
private int pairTries = 0 ;
65
- private Boolean scanning = false ;
66
- private Boolean pairing = false ;
65
+ private boolean scanning = false ;
66
+ private boolean pairing = false ;
67
+ private boolean waitingForDisconnect = false ;
68
+ private boolean wasNotBonded = false ;
67
69
68
70
public enum enumResult {
69
71
None ,
70
72
Found ,
71
73
Connected ,
74
+ AlreadyPaired ,
72
75
Paired ,
73
76
TimeoutScan ,
74
77
TimeoutConnect ,
@@ -165,16 +168,49 @@ private void signalProgress( enumResult state) {
165
168
}
166
169
167
170
@ SuppressLint ("MissingPermission" )
168
- private void signalResultPairedIfBondedAndHardwareVersionDiscovered () {
169
- if (resultDevice .getBondState () == BluetoothDevice .BOND_BONDED ) {
170
- // Wait for service discovery to set resultHardwareVersion
171
- logi ("Bonded resultHardwareVersion " + resultHardwareVersion );
172
- if ( resultHardwareVersion > 0 ) {
173
- signalResult (enumResult .Paired );
174
- }
171
+ private boolean bondedAndHardwareVersionDiscovered () {
172
+ logi ("bondedAndHardwareVersionDiscovered state " + resultDevice .getBondState () + " resultHardwareVersion " + resultHardwareVersion );
173
+ if ( resultDevice .getBondState () != BluetoothDevice .BOND_BONDED ) {
174
+ wasNotBonded = true ;
175
+ return false ;
176
+ }
177
+ // Wait for service discovery to set resultHardwareVersion
178
+ if ( resultHardwareVersion <= 0 ) {
179
+ return false ;
180
+ }
181
+ return true ;
182
+ }
183
+
184
+ @ SuppressLint ("MissingPermission" )
185
+ private boolean startWaitingForDisconnectIfBondedAndHardwareVersionDiscovered () {
186
+ if ( !bondedAndHardwareVersionDiscovered ()) {
187
+ return false ;
175
188
}
189
+ // Wait for micro:bit to disconnect
190
+ waitingForDisconnect = true ;
191
+ delayStopAll ();
192
+ delayStart ( delayCallbackWaitingForDisconnect , 6000 );
193
+ logi ("Start waiting for disconnect" );
194
+ return true ;
176
195
}
177
196
197
+ private void onDisconnect () {
198
+ // If actually pairing, micro:bit will break the connection
199
+ // Allow time for tick to appear
200
+ logi ("onDisconnect" );
201
+ if ( bondedAndHardwareVersionDiscovered ()) {
202
+ delayStopAll ();
203
+ delayStart ( delayCallbackSignalResultPaired , 300 );
204
+ } else if ( waitingForDisconnect ) {
205
+ delayStopAll ();
206
+ delayStart ( delayCallbackSignalResultPaired , 300 );
207
+ } else {
208
+ logi ("ERROR - disconnected" );
209
+ logi ("Prepare delayed retry" );
210
+ gattState = enumGattState .Error ;
211
+ delayStart ( delayCallbackConnect , 1000 );
212
+ }
213
+ }
178
214
private void logi (String message ) {
179
215
if (DEBUG ) {
180
216
Log .i (TAG , "### " + Thread .currentThread ().getId () + " # " + message );
@@ -248,13 +284,15 @@ public void run() {
248
284
}
249
285
}
250
286
};
251
-
287
+
252
288
private final Runnable delayCallbackCheck = new Runnable () {
253
289
@ Override
254
290
public void run () {
255
291
logi ("delayCallbackCheck pairChecks " + pairChecks );
256
292
if (pairing ) {
257
- signalResultPairedIfBondedAndHardwareVersionDiscovered ();
293
+ if ( startWaitingForDisconnectIfBondedAndHardwareVersionDiscovered ()) {
294
+ return ;
295
+ }
258
296
if ( pairChecks > 0 ) {
259
297
// We are connected and polling for bonding
260
298
pairChecks -= 1 ;
@@ -266,6 +304,22 @@ public void run() {
266
304
}
267
305
};
268
306
307
+ private final Runnable delayCallbackWaitingForDisconnect = new Runnable () {
308
+ @ Override
309
+ public void run () {
310
+ logi ("delayCallbackWaitingForDisconnect wasNotBonded = " + wasNotBonded );
311
+ signalResult ( wasNotBonded ? enumResult .Paired : enumResult .AlreadyPaired );
312
+ }
313
+ };
314
+
315
+ private final Runnable delayCallbackSignalResultPaired = new Runnable () {
316
+ @ Override
317
+ public void run () {
318
+ logi ("delayCallbackSignalResultPaired wasNotBonded = " + wasNotBonded );
319
+ signalResult ( wasNotBonded ? enumResult .Paired : enumResult .AlreadyPaired );
320
+ }
321
+ };
322
+
269
323
private void delayStopAll ()
270
324
{
271
325
logi ("delayStopAll" );
@@ -275,6 +329,8 @@ private void delayStopAll()
275
329
mainLooperHandler .removeCallbacks ( delayCallbackDiscover );
276
330
mainLooperHandler .removeCallbacks ( delayCallbackBond );
277
331
mainLooperHandler .removeCallbacks ( delayCallbackCheck );
332
+ mainLooperHandler .removeCallbacks ( delayCallbackWaitingForDisconnect );
333
+ mainLooperHandler .removeCallbacks ( delayCallbackSignalResultPaired );
278
334
}
279
335
280
336
private void delayStop ( Runnable callback )
@@ -460,8 +516,17 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState
460
516
return ;
461
517
}
462
518
519
+ if ( gatt .getDevice ().getBondState () != BluetoothDevice .BOND_BONDED ) {
520
+ wasNotBonded = true ;
521
+ }
522
+
463
523
logi ("onConnectionStateChange " + newState + " status " + status );
464
- if ( status != 0 ) {
524
+ if ( status != BluetoothGatt .GATT_SUCCESS ) {
525
+ if ( newState == STATE_DISCONNECTED ) {
526
+ onDisconnect ();
527
+ return ;
528
+ }
529
+ delayStopAll ();
465
530
pairStop ();
466
531
logi ("ERROR - status" );
467
532
logi ("Prepare for retry after a short delay" );
@@ -487,6 +552,7 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState
487
552
// about 600ms after establishing connection. Values 600 - 1600ms should be OK.
488
553
} else {
489
554
logi ("calling discoverServices()" );
555
+ wasNotBonded = true ;
490
556
gattState = enumGattState .WaitingForServices ;
491
557
boolean success = gatt .discoverServices ();
492
558
if (!success ) {
@@ -502,7 +568,7 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState
502
568
else if ( newState == STATE_DISCONNECTED ) {
503
569
// If actually pairing, micro:bit will break the connection
504
570
logi ("STATE_DISCONNECTED" );
505
- delayStartCheck ();
571
+ onDisconnect ();
506
572
}
507
573
}
508
574
@@ -537,7 +603,10 @@ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
537
603
538
604
gattState = enumGattState .ServicesDiscovered ;
539
605
540
- if (resultDevice .getBondState () == BluetoothDevice .BOND_NONE ) {
606
+ if ( startWaitingForDisconnectIfBondedAndHardwareVersionDiscovered ())
607
+ return ;
608
+
609
+ if ( resultDevice .getBondState () == BluetoothDevice .BOND_NONE ) {
541
610
logi ("Delay calling createBond() to wait for bonding to start automatically" );
542
611
delayStart ( delayCallbackBond , 1500 );
543
612
}
@@ -571,6 +640,7 @@ private Boolean pairConnect() {
571
640
572
641
paramCallback .BLEPairGetActivity ().registerReceiver ( pairReceiver , new IntentFilter (BluetoothDevice .ACTION_BOND_STATE_CHANGED ));
573
642
643
+ waitingForDisconnect = false ;
574
644
resultHardwareVersion = 0 ;
575
645
gattState = enumGattState .Connecting ;
576
646
pairing = true ;
@@ -643,13 +713,16 @@ public void onReceive(Context context, Intent intent) {
643
713
final int state = intent .getIntExtra (BluetoothDevice .EXTRA_BOND_STATE , BluetoothDevice .ERROR );
644
714
final int prevState = intent .getIntExtra (BluetoothDevice .EXTRA_PREVIOUS_BOND_STATE , BluetoothDevice .ERROR );
645
715
logi ("pairReceiver -" + " name = " + name + " addr = " + addr + " state = " + state + " prevState = " + prevState );
716
+ if ( state != BluetoothDevice .BOND_BONDED && prevState != BluetoothDevice .BOND_BONDED ) {
717
+ wasNotBonded = true ;
718
+ }
646
719
if (name == null || name .isEmpty () || addr .isEmpty ()) {
647
720
return ;
648
721
}
649
722
// Check the changed device is the one we are trying to pair
650
723
if ( pairing && nameIsMicrobitWithCode (device .getName (), paramCallback .BLEPairGetDeviceCode ())) {
651
724
if (state == BluetoothDevice .BOND_BONDED ) {
652
- signalResultPairedIfBondedAndHardwareVersionDiscovered ();
725
+ startWaitingForDisconnectIfBondedAndHardwareVersionDiscovered ();
653
726
}
654
727
}
655
728
}
0 commit comments