Skip to content

Commit 8c67892

Browse files
committed
fix(android): correctly update device state on disconnect
1 parent 0644fb9 commit 8c67892

File tree

1 file changed

+105
-104
lines changed

1 file changed

+105
-104
lines changed

src/bluetooth.android.ts

Lines changed: 105 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
AdvertismentData,
66
BluetoothCommon,
77
BluetoothError,
8+
BluetoothOptions,
89
CLog,
910
CLogTypes,
1011
ConnectOptions,
@@ -24,7 +25,6 @@ import {
2425
WriteOptions,
2526
bluetoothEnabled,
2627
prepareArgs,
27-
BluetoothOptions,
2828
} from './bluetooth.common';
2929
import PQueue from 'p-queue';
3030
import { Trace } from '@nativescript/core';
@@ -1151,15 +1151,15 @@ export class Bluetooth extends BluetoothCommon {
11511151
this.LeScanCallback = new LeScanCallbackVar(new WeakRef(this));
11521152
}
11531153
if (typeof restoreIdentifierOrOptions === 'object' && !!restoreIdentifierOrOptions.disableAndroidQueue) {
1154-
this.gattQueue = undefined;
1154+
this.gattQueue = undefined;
11551155
} else {
1156-
this.gattQueue = new PQueue({ concurrency: 1 });
1156+
this.gattQueue = new PQueue({ concurrency: 1 });
11571157
}
11581158
}
11591159

11601160
clear() {
11611161
if (this.gattQueue) {
1162-
this.gattQueue.clear();
1162+
this.gattQueue.clear();
11631163
}
11641164
}
11651165
broadcastRegistered = false;
@@ -1808,7 +1808,7 @@ export class Bluetooth extends BluetoothCommon {
18081808

18091809
private addToGattQueue(p: () => Promise<any>) {
18101810
if (this.gattQueue) {
1811-
return this.gattQueue.add(p);
1811+
return this.gattQueue.add(p);
18121812
}
18131813
return p();
18141814
}
@@ -2299,7 +2299,7 @@ export class Bluetooth extends BluetoothCommon {
22992299
const stateObject = this.connections[pUUID];
23002300
stateObject.onNotifyCallbacks = stateObject.onNotifyCallbacks || {};
23012301
stateObject.onNotifyCallbacks[key] = function (result) {
2302-
onNotify(result);
2302+
onNotify(result);
23032303
};
23042304
resolve();
23052305
clearListeners();
@@ -2339,110 +2339,110 @@ export class Bluetooth extends BluetoothCommon {
23392339
return this.addToQueue(
23402340
args,
23412341
(wrapper) =>
2342-
new Promise<void>((resolve, reject) => {
2343-
const gatt = wrapper.gatt;
2344-
const bluetoothGattService = wrapper.bluetoothGattService;
2345-
const characteristicUUID = stringToUuid(args.characteristicUUID);
2346-
2347-
const characteristic = this._findNotifyCharacteristic(bluetoothGattService, characteristicUUID);
2348-
if (Trace.isEnabled()) {
2349-
CLog(CLogTypes.info, `${methodName} ---- peripheralUUID:${args.peripheralUUID} serviceUUID:${args.serviceUUID} characteristicUUID:${args.characteristicUUID}`);
2350-
}
2351-
if (!characteristic) {
2352-
return reject(
2353-
new BluetoothError(BluetoothCommon.msg_no_characteristic, {
2354-
method: methodName,
2355-
arguments: args,
2356-
})
2357-
);
2358-
}
2359-
2360-
if (!gatt.setCharacteristicNotification(characteristic, false)) {
2361-
return reject(
2362-
new BluetoothError(BluetoothCommon.msg_error_function_call, {
2363-
method: 'setCharacteristicNotification',
2364-
arguments: args,
2365-
})
2366-
);
2367-
}
2368-
2369-
const clientCharacteristicConfigId = stringToUuid('2902');
2370-
let bluetoothGattDescriptor = characteristic.getDescriptor(clientCharacteristicConfigId) as android.bluetooth.BluetoothGattDescriptor;
2371-
if (!bluetoothGattDescriptor) {
2372-
bluetoothGattDescriptor = new android.bluetooth.BluetoothGattDescriptor(clientCharacteristicConfigId, android.bluetooth.BluetoothGattDescriptor.PERMISSION_WRITE);
2373-
bluetoothGattDescriptor.setValue(android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
2374-
characteristic.addDescriptor(bluetoothGattDescriptor);
2375-
if (Trace.isEnabled()) {
2376-
CLog(CLogTypes.info, methodName, '---- descriptor:', bluetoothGattDescriptor);
2377-
}
2378-
// Any creation error will trigger the global catch. Ok.
2379-
}
2380-
2381-
// prefer notify over indicate
2382-
if ((characteristic.getProperties() & android.bluetooth.BluetoothGattCharacteristic.PROPERTY_NOTIFY) !== 0) {
2383-
bluetoothGattDescriptor.setValue(android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
2384-
} else if ((characteristic.getProperties() & android.bluetooth.BluetoothGattCharacteristic.PROPERTY_INDICATE) !== 0) {
2385-
bluetoothGattDescriptor.setValue(android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
2386-
} else {
2387-
return reject(
2388-
new BluetoothError(BluetoothCommon.msg_characteristic_cant_notify, {
2389-
method: methodName,
2390-
arguments: args,
2391-
})
2392-
);
2393-
}
2394-
2395-
const pUUID = args.peripheralUUID;
2396-
const cUUID = uuidToString(characteristic.getUuid());
2397-
const sUUID = uuidToString(characteristic.getService().getUuid());
2398-
2399-
const key = sUUID + '/' + cUUID;
2400-
this.attachSubDelegate(
2401-
{methodName, args, resolve, reject},
2402-
(clearListeners, onError) => ({
2403-
onDescriptorWrite: (gatt: android.bluetooth.BluetoothGatt, descriptor: android.bluetooth.BluetoothGattDescriptor, status: number) => {
2404-
const device = gatt.getDevice();
2405-
let UUID: string = null;
2406-
if (device == null) {
2407-
// happens some time, why ... ?
2408-
} else {
2409-
UUID = device.getAddress();
2410-
}
2411-
2412-
if (UUID === pUUID && cUUID === args.characteristicUUID && sUUID === args.serviceUUID) {
2413-
if (status === GATT_SUCCESS && descriptor.getValue() === android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE) {
2414-
// Only delete callback on successful disable
2415-
const stateObject = this.connections[args.peripheralUUID];
2416-
if (stateObject && stateObject.onNotifyCallbacks) {
2417-
const key = args.serviceUUID + '/' + args.characteristicUUID;
2418-
delete stateObject.onNotifyCallbacks[key];
2419-
}
2420-
resolve();
2421-
clearListeners();
2422-
} else {
2342+
new Promise<void>((resolve, reject) => {
2343+
const gatt = wrapper.gatt;
2344+
const bluetoothGattService = wrapper.bluetoothGattService;
2345+
const characteristicUUID = stringToUuid(args.characteristicUUID);
2346+
2347+
const characteristic = this._findNotifyCharacteristic(bluetoothGattService, characteristicUUID);
2348+
if (Trace.isEnabled()) {
2349+
CLog(CLogTypes.info, `${methodName} ---- peripheralUUID:${args.peripheralUUID} serviceUUID:${args.serviceUUID} characteristicUUID:${args.characteristicUUID}`);
2350+
}
2351+
if (!characteristic) {
2352+
return reject(
2353+
new BluetoothError(BluetoothCommon.msg_no_characteristic, {
2354+
method: methodName,
2355+
arguments: args,
2356+
})
2357+
);
2358+
}
2359+
2360+
if (!gatt.setCharacteristicNotification(characteristic, false)) {
2361+
return reject(
2362+
new BluetoothError(BluetoothCommon.msg_error_function_call, {
2363+
method: 'setCharacteristicNotification',
2364+
arguments: args,
2365+
})
2366+
);
2367+
}
2368+
2369+
const clientCharacteristicConfigId = stringToUuid('2902');
2370+
let bluetoothGattDescriptor = characteristic.getDescriptor(clientCharacteristicConfigId) as android.bluetooth.BluetoothGattDescriptor;
2371+
if (!bluetoothGattDescriptor) {
2372+
bluetoothGattDescriptor = new android.bluetooth.BluetoothGattDescriptor(clientCharacteristicConfigId, android.bluetooth.BluetoothGattDescriptor.PERMISSION_WRITE);
2373+
bluetoothGattDescriptor.setValue(android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
2374+
characteristic.addDescriptor(bluetoothGattDescriptor);
2375+
if (Trace.isEnabled()) {
2376+
CLog(CLogTypes.info, methodName, '---- descriptor:', bluetoothGattDescriptor);
2377+
}
2378+
// Any creation error will trigger the global catch. Ok.
2379+
}
2380+
2381+
// prefer notify over indicate
2382+
if ((characteristic.getProperties() & android.bluetooth.BluetoothGattCharacteristic.PROPERTY_NOTIFY) !== 0) {
2383+
bluetoothGattDescriptor.setValue(android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
2384+
} else if ((characteristic.getProperties() & android.bluetooth.BluetoothGattCharacteristic.PROPERTY_INDICATE) !== 0) {
2385+
bluetoothGattDescriptor.setValue(android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
2386+
} else {
2387+
return reject(
2388+
new BluetoothError(BluetoothCommon.msg_characteristic_cant_notify, {
2389+
method: methodName,
2390+
arguments: args,
2391+
})
2392+
);
2393+
}
2394+
2395+
const pUUID = args.peripheralUUID;
2396+
const cUUID = uuidToString(characteristic.getUuid());
2397+
const sUUID = uuidToString(characteristic.getService().getUuid());
2398+
2399+
const key = sUUID + '/' + cUUID;
2400+
this.attachSubDelegate(
2401+
{methodName, args, resolve, reject},
2402+
(clearListeners, onError) => ({
2403+
onDescriptorWrite: (gatt: android.bluetooth.BluetoothGatt, descriptor: android.bluetooth.BluetoothGattDescriptor, status: number) => {
2404+
const device = gatt.getDevice();
2405+
let UUID: string = null;
2406+
if (device == null) {
2407+
// happens some time, why ... ?
2408+
} else {
2409+
UUID = device.getAddress();
2410+
}
2411+
2412+
if (UUID === pUUID && cUUID === args.characteristicUUID && sUUID === args.serviceUUID) {
2413+
if (status === GATT_SUCCESS && descriptor.getValue() === android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE) {
2414+
// Only delete callback on successful disable
2415+
const stateObject = this.connections[args.peripheralUUID];
2416+
if (stateObject && stateObject.onNotifyCallbacks) {
2417+
const key = args.serviceUUID + '/' + args.characteristicUUID;
2418+
delete stateObject.onNotifyCallbacks[key];
2419+
}
2420+
resolve();
2421+
clearListeners();
2422+
} else {
2423+
onError(
2424+
new BluetoothError(BluetoothCommon.msg_error_function_call, {
2425+
arguments: args,
2426+
method: 'writeDescriptor',
2427+
status,
2428+
})
2429+
);
2430+
}
2431+
}
2432+
},
2433+
}),
2434+
(onError) => {
2435+
if (!gatt.writeDescriptor(bluetoothGattDescriptor)) {
24232436
onError(
24242437
new BluetoothError(BluetoothCommon.msg_error_function_call, {
2425-
arguments: args,
24262438
method: 'writeDescriptor',
2427-
status,
2439+
arguments: args,
24282440
})
24292441
);
24302442
}
2431-
}
2432-
},
2433-
}),
2434-
(onError) => {
2435-
if (!gatt.writeDescriptor(bluetoothGattDescriptor)) {
2436-
onError(
2437-
new BluetoothError(BluetoothCommon.msg_error_function_call, {
2438-
method: 'writeDescriptor',
2439-
arguments: args,
2440-
})
2441-
);
2442-
}
2443-
},
2444-
);
2445-
})
2443+
},
2444+
);
2445+
})
24462446
);
24472447
}
24482448

@@ -2629,6 +2629,7 @@ export class Bluetooth extends BluetoothCommon {
26292629
});
26302630

26312631
const stateObject = this.connections[address];
2632+
stateObject.state = 'disconnected';
26322633
if (stateObject && stateObject.onDisconnected) {
26332634
stateObject.onDisconnected({
26342635
UUID: address,

0 commit comments

Comments
 (0)