react-native-ble-manager 12.3.0 → 12.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/it/innove/BleManager.java +10 -4
- package/android/src/main/java/it/innove/DefaultPeripheral.java +11 -10
- package/android/src/main/java/it/innove/DefaultScanManager.java +17 -14
- package/android/src/main/java/it/innove/Peripheral.java +121 -80
- package/android/src/main/java/it/innove/ScanManager.java +1 -1
- package/dist/cjs/NativeBleManager.d.ts +27 -26
- package/dist/cjs/NativeBleManager.js +1 -0
- package/dist/cjs/NativeBleManager.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -1
- package/dist/cjs/index.js +27 -5
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types.d.ts +7 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/NativeBleManager.d.ts +27 -26
- package/dist/esm/NativeBleManager.js +1 -0
- package/dist/esm/NativeBleManager.js.map +1 -1
- package/dist/esm/index.d.ts +6 -1
- package/dist/esm/index.js +28 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.d.ts +7 -1
- package/dist/esm/types.js.map +1 -1
- package/ios/BleManager.mm +7 -11
- package/ios/Helper.swift +166 -110
- package/ios/NotifyBufferContainer.swift +11 -12
- package/ios/SwiftBleManager.swift +1224 -586
- package/package.json +1 -1
- package/src/NativeBleManager.ts +42 -82
- package/src/index.ts +34 -25
- package/src/types.ts +7 -1
|
@@ -40,7 +40,7 @@ import java.util.List;
|
|
|
40
40
|
import java.util.Map;
|
|
41
41
|
import java.util.Set;
|
|
42
42
|
|
|
43
|
-
class BleManager extends NativeBleManagerSpec {
|
|
43
|
+
public class BleManager extends NativeBleManagerSpec {
|
|
44
44
|
|
|
45
45
|
public static final String LOG_TAG = "RNBleManager";
|
|
46
46
|
private static final int ENABLE_REQUEST = 539;
|
|
@@ -282,6 +282,12 @@ class BleManager extends NativeBleManagerSpec {
|
|
|
282
282
|
Log.d(LOG_TAG, "BleManager initialized");
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
@ReactMethod
|
|
286
|
+
public void isStarted(Callback callback) {
|
|
287
|
+
Log.d(LOG_TAG, "isStarted");
|
|
288
|
+
callback.invoke(null, scanManager != null);
|
|
289
|
+
}
|
|
290
|
+
|
|
285
291
|
@SuppressLint("MissingPermission")
|
|
286
292
|
@ReactMethod
|
|
287
293
|
public void enableBluetooth(Callback callback) {
|
|
@@ -310,7 +316,7 @@ class BleManager extends NativeBleManagerSpec {
|
|
|
310
316
|
}
|
|
311
317
|
|
|
312
318
|
@ReactMethod
|
|
313
|
-
public void scan(
|
|
319
|
+
public void scan(ReadableMap scanningOptions,
|
|
314
320
|
Callback callback) {
|
|
315
321
|
Log.d(LOG_TAG, "scan");
|
|
316
322
|
if (getBluetoothAdapter() == null) {
|
|
@@ -333,7 +339,7 @@ class BleManager extends NativeBleManagerSpec {
|
|
|
333
339
|
}
|
|
334
340
|
|
|
335
341
|
if (scanManager != null)
|
|
336
|
-
scanManager.scan(
|
|
342
|
+
scanManager.scan(scanningOptions, callback);
|
|
337
343
|
}
|
|
338
344
|
|
|
339
345
|
@SuppressLint("NewApi") // NOTE: constructor checks the API version.
|
|
@@ -448,7 +454,7 @@ class BleManager extends NativeBleManagerSpec {
|
|
|
448
454
|
|
|
449
455
|
@ReactMethod
|
|
450
456
|
public void startNotificationWithBuffer(String deviceUUID, String serviceUUID, String characteristicUUID,
|
|
451
|
-
|
|
457
|
+
double bufferLength, Callback callback) {
|
|
452
458
|
Log.d(LOG_TAG, "startNotification");
|
|
453
459
|
if (serviceUUID == null || characteristicUUID == null) {
|
|
454
460
|
callback.invoke("ServiceUUID and characteristicUUID required.");
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
package it.innove;
|
|
2
2
|
|
|
3
|
+
import static it.innove.BleManager.LOG_TAG;
|
|
4
|
+
|
|
3
5
|
import android.bluetooth.BluetoothDevice;
|
|
4
6
|
import android.bluetooth.le.ScanRecord;
|
|
5
7
|
import android.bluetooth.le.ScanResult;
|
|
6
8
|
import android.os.Build;
|
|
7
9
|
import android.os.ParcelUuid;
|
|
8
10
|
import android.annotation.SuppressLint;
|
|
11
|
+
import android.util.Log;
|
|
9
12
|
import android.util.SparseArray;
|
|
10
13
|
|
|
11
14
|
import com.facebook.react.bridge.Arguments;
|
|
12
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
13
|
-
import com.facebook.react.bridge.ReactContext;
|
|
14
15
|
import com.facebook.react.bridge.WritableArray;
|
|
15
16
|
import com.facebook.react.bridge.WritableMap;
|
|
16
17
|
|
|
@@ -25,7 +26,7 @@ public class DefaultPeripheral extends Peripheral {
|
|
|
25
26
|
private ScanResult scanResult;
|
|
26
27
|
|
|
27
28
|
public DefaultPeripheral(BleManager bleManager, ScanResult result) {
|
|
28
|
-
super(result.getDevice(), result.getRssi(), result.getScanRecord().getBytes(), bleManager);
|
|
29
|
+
super(result.getDevice(), result.getRssi(), Objects.requireNonNull(result.getScanRecord()).getBytes(), bleManager);
|
|
29
30
|
this.advertisingData = result.getScanRecord();
|
|
30
31
|
this.scanResult = result;
|
|
31
32
|
}
|
|
@@ -40,9 +41,9 @@ public class DefaultPeripheral extends Peripheral {
|
|
|
40
41
|
WritableMap advertising = Arguments.createMap();
|
|
41
42
|
|
|
42
43
|
try {
|
|
43
|
-
String name =
|
|
44
|
-
if (name == null) {
|
|
45
|
-
name =
|
|
44
|
+
String name = getSafeDeviceName();
|
|
45
|
+
if (name == null && scanResult != null && scanResult.getScanRecord() != null) {
|
|
46
|
+
name = scanResult.getScanRecord().getDeviceName();
|
|
46
47
|
}
|
|
47
48
|
map.putString("name", name);
|
|
48
49
|
map.putString("id", device.getAddress()); // mac address
|
|
@@ -50,7 +51,7 @@ public class DefaultPeripheral extends Peripheral {
|
|
|
50
51
|
|
|
51
52
|
advertising.putMap("rawData", byteArrayToWritableMap(advertisingDataBytes));
|
|
52
53
|
|
|
53
|
-
if (
|
|
54
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
54
55
|
// We can check if peripheral is connectable using the scanresult
|
|
55
56
|
if (this.scanResult != null) {
|
|
56
57
|
advertising.putBoolean("isConnectable", scanResult.isConnectable());
|
|
@@ -66,7 +67,7 @@ public class DefaultPeripheral extends Peripheral {
|
|
|
66
67
|
advertising.putString("localName", deviceName.replace("\0", ""));
|
|
67
68
|
|
|
68
69
|
WritableArray serviceUuids = Arguments.createArray();
|
|
69
|
-
if (advertisingData.getServiceUuids() != null && advertisingData.getServiceUuids().
|
|
70
|
+
if (advertisingData.getServiceUuids() != null && !advertisingData.getServiceUuids().isEmpty()) {
|
|
70
71
|
for (ParcelUuid uuid : advertisingData.getServiceUuids()) {
|
|
71
72
|
serviceUuids.pushString(UUIDHelper.uuidToString(uuid.getUuid()));
|
|
72
73
|
}
|
|
@@ -106,7 +107,7 @@ public class DefaultPeripheral extends Peripheral {
|
|
|
106
107
|
|
|
107
108
|
map.putMap("advertising", advertising);
|
|
108
109
|
} catch (Exception e) { // this shouldn't happen
|
|
109
|
-
e
|
|
110
|
+
Log.e(LOG_TAG, "asWritableMap error", e);
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
return map;
|
|
@@ -115,6 +116,6 @@ public class DefaultPeripheral extends Peripheral {
|
|
|
115
116
|
public void updateData(ScanResult result) {
|
|
116
117
|
scanResult = result;
|
|
117
118
|
advertisingData = result.getScanRecord();
|
|
118
|
-
advertisingDataBytes = advertisingData.getBytes();
|
|
119
|
+
advertisingDataBytes = advertisingData != null ? advertisingData.getBytes() : null;
|
|
119
120
|
}
|
|
120
121
|
}
|
|
@@ -36,6 +36,7 @@ import com.facebook.react.bridge.WritableMap;
|
|
|
36
36
|
import java.util.ArrayList;
|
|
37
37
|
import java.util.Arrays;
|
|
38
38
|
import java.util.List;
|
|
39
|
+
import java.util.Objects;
|
|
39
40
|
|
|
40
41
|
@SuppressLint("MissingPermission")
|
|
41
42
|
public class DefaultScanManager extends ScanManager {
|
|
@@ -65,7 +66,7 @@ public class DefaultScanManager extends ScanManager {
|
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
@Override
|
|
68
|
-
public void scan(
|
|
69
|
+
public void scan(ReadableMap options, Callback callback) {
|
|
69
70
|
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
|
|
70
71
|
List<ScanFilter> filters = new ArrayList<>();
|
|
71
72
|
|
|
@@ -77,16 +78,14 @@ public class DefaultScanManager extends ScanManager {
|
|
|
77
78
|
scanSettingsBuilder.setScanMode(options.getInt("scanMode"));
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
scanSettingsBuilder.setCallbackType(options.getInt("callbackType"));
|
|
89
|
-
}
|
|
81
|
+
if (options.hasKey("numberOfMatches")) {
|
|
82
|
+
scanSettingsBuilder.setNumOfMatches(options.getInt("numberOfMatches"));
|
|
83
|
+
}
|
|
84
|
+
if (options.hasKey("matchMode")) {
|
|
85
|
+
scanSettingsBuilder.setMatchMode(options.getInt("matchMode"));
|
|
86
|
+
}
|
|
87
|
+
if (options.hasKey("callbackType")) {
|
|
88
|
+
scanSettingsBuilder.setCallbackType(options.getInt("callbackType"));
|
|
90
89
|
}
|
|
91
90
|
|
|
92
91
|
if (options.hasKey("reportDelay")) {
|
|
@@ -103,9 +102,10 @@ public class DefaultScanManager extends ScanManager {
|
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
|
|
106
|
-
|
|
105
|
+
ReadableArray serviceUUIDs = options.getArray("serviceUUIDs");
|
|
106
|
+
if (serviceUUIDs != null && serviceUUIDs.size() > 0) {
|
|
107
107
|
for (int i = 0; i < serviceUUIDs.size(); i++) {
|
|
108
|
-
ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUIDHelper.uuidFromString(serviceUUIDs.getString(i)))).build();
|
|
108
|
+
ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUIDHelper.uuidFromString(Objects.requireNonNull(serviceUUIDs.getString(i))))).build();
|
|
109
109
|
filters.add(filter);
|
|
110
110
|
Log.d(BleManager.LOG_TAG, "Filter service: " + serviceUUIDs.getString(i));
|
|
111
111
|
}
|
|
@@ -221,6 +221,7 @@ public class DefaultScanManager extends ScanManager {
|
|
|
221
221
|
|
|
222
222
|
isScanning = true;
|
|
223
223
|
|
|
224
|
+
long scanSeconds = (long) options.getDouble("seconds");
|
|
224
225
|
if (scanSeconds > 0) {
|
|
225
226
|
Thread thread = new Thread() {
|
|
226
227
|
private final int currentScanSession = scanSessionId.incrementAndGet();
|
|
@@ -337,7 +338,9 @@ public class DefaultScanManager extends ScanManager {
|
|
|
337
338
|
if (scanner != null) {
|
|
338
339
|
try {
|
|
339
340
|
if (scanningWithIntent && scanPendingIntent != null) {
|
|
340
|
-
|
|
341
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
342
|
+
scanner.stopScan(scanPendingIntent);
|
|
343
|
+
}
|
|
341
344
|
} else {
|
|
342
345
|
scanner.stopScan(mScanCallback);
|
|
343
346
|
}
|
|
@@ -2,6 +2,7 @@ package it.innove;
|
|
|
2
2
|
|
|
3
3
|
import static com.facebook.react.common.ReactConstants.TAG;
|
|
4
4
|
|
|
5
|
+
import android.Manifest;
|
|
5
6
|
import android.annotation.SuppressLint;
|
|
6
7
|
import android.app.Activity;
|
|
7
8
|
import android.bluetooth.BluetoothDevice;
|
|
@@ -12,7 +13,7 @@ import android.bluetooth.BluetoothGattDescriptor;
|
|
|
12
13
|
import android.bluetooth.BluetoothGattService;
|
|
13
14
|
import android.bluetooth.BluetoothProfile;
|
|
14
15
|
import android.bluetooth.BluetoothStatusCodes;
|
|
15
|
-
|
|
16
|
+
import android.content.pm.PackageManager;
|
|
16
17
|
import android.content.Context;
|
|
17
18
|
import android.os.Build;
|
|
18
19
|
import android.os.Handler;
|
|
@@ -22,6 +23,7 @@ import android.util.Log;
|
|
|
22
23
|
|
|
23
24
|
import androidx.annotation.NonNull;
|
|
24
25
|
import androidx.annotation.Nullable;
|
|
26
|
+
import androidx.core.content.ContextCompat;
|
|
25
27
|
|
|
26
28
|
import com.facebook.react.bridge.Arguments;
|
|
27
29
|
import com.facebook.react.bridge.Callback;
|
|
@@ -79,7 +81,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
79
81
|
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
80
82
|
private boolean commandQueueBusy = false;
|
|
81
83
|
|
|
82
|
-
private
|
|
84
|
+
private final Queue<byte[]> writeQueue = new LinkedList<>();
|
|
83
85
|
|
|
84
86
|
public Peripheral(BluetoothDevice device, int advertisingRSSI, byte[] scanRecord, BleManager bleManager) {
|
|
85
87
|
this.device = device;
|
|
@@ -160,10 +162,10 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
160
162
|
// bt_btif : Register with GATT stack failed.
|
|
161
163
|
|
|
162
164
|
public void disconnect(final Callback callback, final boolean force) {
|
|
165
|
+
connected = false;
|
|
163
166
|
mainHandler.post(() -> {
|
|
164
167
|
errorAndClearAllCallbacks("Disconnect called before the command completed");
|
|
165
168
|
resetQueuesAndBuffers();
|
|
166
|
-
connected = false;
|
|
167
169
|
|
|
168
170
|
if (gatt != null) {
|
|
169
171
|
try {
|
|
@@ -190,11 +192,11 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
190
192
|
WritableMap advertising = Arguments.createMap();
|
|
191
193
|
|
|
192
194
|
try {
|
|
193
|
-
|
|
195
|
+
String name = getSafeDeviceName();
|
|
196
|
+
map.putString("name", name);
|
|
194
197
|
map.putString("id", device.getAddress()); // mac address
|
|
195
198
|
map.putInt("rssi", advertisingRSSI);
|
|
196
199
|
|
|
197
|
-
String name = device.getName();
|
|
198
200
|
if (name != null)
|
|
199
201
|
advertising.putString("localName", name);
|
|
200
202
|
|
|
@@ -211,6 +213,23 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
211
213
|
return map;
|
|
212
214
|
}
|
|
213
215
|
|
|
216
|
+
@Nullable
|
|
217
|
+
protected String getSafeDeviceName() {
|
|
218
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
219
|
+
Context context = bleManager != null ? bleManager.getReactContext() : null;
|
|
220
|
+
if (context == null) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT)
|
|
225
|
+
!= PackageManager.PERMISSION_GRANTED) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return device.getName();
|
|
231
|
+
}
|
|
232
|
+
|
|
214
233
|
public WritableMap asWritableMap(BluetoothGatt gatt) {
|
|
215
234
|
|
|
216
235
|
WritableMap map = asWritableMap();
|
|
@@ -219,13 +238,13 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
219
238
|
WritableArray characteristicsArray = Arguments.createArray();
|
|
220
239
|
|
|
221
240
|
if (connected && gatt != null) {
|
|
222
|
-
for (Iterator<BluetoothGattService> it = gatt.getServices().iterator(); it.hasNext();) {
|
|
241
|
+
for (Iterator<BluetoothGattService> it = gatt.getServices().iterator(); it.hasNext(); ) {
|
|
223
242
|
BluetoothGattService service = it.next();
|
|
224
243
|
WritableMap serviceMap = Arguments.createMap();
|
|
225
244
|
serviceMap.putString("uuid", UUIDHelper.uuidToString(service.getUuid()));
|
|
226
245
|
|
|
227
246
|
for (Iterator<BluetoothGattCharacteristic> itCharacteristic = service.getCharacteristics()
|
|
228
|
-
.iterator(); itCharacteristic.hasNext();) {
|
|
247
|
+
.iterator(); itCharacteristic.hasNext(); ) {
|
|
229
248
|
BluetoothGattCharacteristic characteristic = itCharacteristic.next();
|
|
230
249
|
WritableMap characteristicsMap = Arguments.createMap();
|
|
231
250
|
|
|
@@ -297,15 +316,12 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
297
316
|
for (Callback retrieveServicesCallback : retrieveServicesCallbacks) {
|
|
298
317
|
retrieveServicesCallback.invoke("Error during service retrieval: gatt is null");
|
|
299
318
|
}
|
|
300
|
-
}
|
|
301
|
-
else if (status == BluetoothGatt.GATT_SUCCESS)
|
|
302
|
-
{
|
|
319
|
+
} else if (status == BluetoothGatt.GATT_SUCCESS) {
|
|
303
320
|
for (Callback retrieveServicesCallback : retrieveServicesCallbacks) {
|
|
304
321
|
WritableMap map = this.asWritableMap(gatt);
|
|
305
322
|
retrieveServicesCallback.invoke(null, map);
|
|
306
323
|
}
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
324
|
+
} else {
|
|
309
325
|
for (Callback retrieveServicesCallback : retrieveServicesCallbacks) {
|
|
310
326
|
retrieveServicesCallback.invoke("Error during service retrieval.");
|
|
311
327
|
}
|
|
@@ -370,12 +386,20 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
370
386
|
connected = false;
|
|
371
387
|
clearBuffers();
|
|
372
388
|
}
|
|
389
|
+
|
|
373
390
|
@Override
|
|
374
391
|
public void onConnectionStateChange(BluetoothGatt gatta, int status, final int newState) {
|
|
375
392
|
|
|
376
393
|
Log.d(BleManager.LOG_TAG, "onConnectionStateChange to " + newState + " on peripheral: " + device.getAddress()
|
|
377
394
|
+ " with status " + status);
|
|
378
395
|
|
|
396
|
+
// We immediately update the internal connection status
|
|
397
|
+
if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) {
|
|
398
|
+
connected = true;
|
|
399
|
+
} else if (newState == BluetoothProfile.STATE_DISCONNECTED || status != BluetoothGatt.GATT_SUCCESS) {
|
|
400
|
+
connected = false;
|
|
401
|
+
}
|
|
402
|
+
|
|
379
403
|
mainHandler.post(() -> {
|
|
380
404
|
gatt = gatta;
|
|
381
405
|
|
|
@@ -385,8 +409,6 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
385
409
|
|
|
386
410
|
connecting = false;
|
|
387
411
|
if (newState == BluetoothProfile.STATE_CONNECTED && status == BluetoothGatt.GATT_SUCCESS) {
|
|
388
|
-
connected = true;
|
|
389
|
-
|
|
390
412
|
sendConnectionEvent(device, status);
|
|
391
413
|
|
|
392
414
|
Log.d(BleManager.LOG_TAG, "Connected to: " + device.getAddress());
|
|
@@ -420,7 +442,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
420
442
|
advertisingDataBytes = data;
|
|
421
443
|
}
|
|
422
444
|
|
|
423
|
-
|
|
445
|
+
/// ///
|
|
424
446
|
|
|
425
447
|
@Override
|
|
426
448
|
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
|
|
@@ -456,7 +478,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
456
478
|
return;
|
|
457
479
|
}
|
|
458
480
|
}
|
|
459
|
-
|
|
481
|
+
|
|
460
482
|
WritableMap map = Arguments.createMap();
|
|
461
483
|
map.putString("peripheral", device.getAddress());
|
|
462
484
|
map.putString("characteristic", charString);
|
|
@@ -480,6 +502,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
480
502
|
onCharacteristicRead(gatt, characteristic, characteristic.getValue(), status);
|
|
481
503
|
}
|
|
482
504
|
}
|
|
505
|
+
|
|
483
506
|
@Override
|
|
484
507
|
public void onCharacteristicRead(@NonNull final BluetoothGatt gatt,
|
|
485
508
|
@NonNull final BluetoothGattCharacteristic characteristic,
|
|
@@ -517,27 +540,28 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
517
540
|
super.onCharacteristicWrite(gatt, characteristic, status);
|
|
518
541
|
|
|
519
542
|
mainHandler.post(() -> {
|
|
520
|
-
if (writeQueue.
|
|
521
|
-
byte[] data = writeQueue.
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
543
|
+
if (!writeQueue.isEmpty()) {
|
|
544
|
+
byte[] data = writeQueue.poll();
|
|
545
|
+
doWrite(characteristic, data);
|
|
546
|
+
} else {
|
|
547
|
+
if (status != BluetoothGatt.GATT_SUCCESS) {
|
|
548
|
+
if (status == GATT_AUTH_FAIL || status == GATT_INSUFFICIENT_AUTHENTICATION) {
|
|
549
|
+
Log.d(BleManager.LOG_TAG, "Write needs bonding");
|
|
550
|
+
// *not* doing completedCommand()
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
for (Callback writeCallback : writeCallbacks) {
|
|
554
|
+
writeCallback.invoke("Error writing " + characteristic.getUuid() + " status=" + status, null);
|
|
555
|
+
}
|
|
556
|
+
writeCallbacks.clear();
|
|
557
|
+
} else if (!writeCallbacks.isEmpty()) {
|
|
558
|
+
for (Callback writeCallback : writeCallbacks) {
|
|
559
|
+
writeCallback.invoke();
|
|
560
|
+
}
|
|
561
|
+
writeCallbacks.clear();
|
|
537
562
|
}
|
|
538
|
-
|
|
563
|
+
completedCommand();
|
|
539
564
|
}
|
|
540
|
-
completedCommand();
|
|
541
565
|
});
|
|
542
566
|
}
|
|
543
567
|
|
|
@@ -699,7 +723,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
699
723
|
// Then write to descriptor
|
|
700
724
|
registerNotifyCallbacks.addLast(callback);
|
|
701
725
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
702
|
-
result &=
|
|
726
|
+
result &= BluetoothStatusCodes.SUCCESS == gatt.writeDescriptor(descriptor, finalValue);
|
|
703
727
|
} else {
|
|
704
728
|
descriptor.setValue(finalValue);
|
|
705
729
|
result &= gatt.writeDescriptor(descriptor);
|
|
@@ -752,7 +776,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
752
776
|
// until we find the best match
|
|
753
777
|
// This function prefers Notify over Indicate
|
|
754
778
|
private BluetoothGattCharacteristic findNotifyCharacteristic(BluetoothGattService service,
|
|
755
|
-
|
|
779
|
+
UUID characteristicUUID) {
|
|
756
780
|
|
|
757
781
|
try {
|
|
758
782
|
// Check for Notify first
|
|
@@ -810,7 +834,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
810
834
|
}
|
|
811
835
|
|
|
812
836
|
public void readDescriptor(UUID serviceUUID, UUID characteristicUUID, UUID descriptorUUID,
|
|
813
|
-
|
|
837
|
+
final Callback callback) {
|
|
814
838
|
enqueue(() -> {
|
|
815
839
|
if (!isConnected() || gatt == null) {
|
|
816
840
|
callback.invoke("Device is not connected", null);
|
|
@@ -893,9 +917,8 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
893
917
|
writeCallback.invoke("writeDescriptor failed for descriptor: " + descriptor.getUuid(), null);
|
|
894
918
|
}
|
|
895
919
|
writeDescriptorCallbacks.clear();
|
|
920
|
+
completedCommand();
|
|
896
921
|
}
|
|
897
|
-
|
|
898
|
-
completedCommand();
|
|
899
922
|
});
|
|
900
923
|
}
|
|
901
924
|
|
|
@@ -939,14 +962,6 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
939
962
|
return;
|
|
940
963
|
}
|
|
941
964
|
|
|
942
|
-
// Check if we still have a valid gatt object
|
|
943
|
-
if (gatt == null) {
|
|
944
|
-
Log.d(BleManager.LOG_TAG, "Error, gatt is null. Fill all callbacks with an error");
|
|
945
|
-
errorAndClearAllCallbacks("Gatt is null");
|
|
946
|
-
resetQueuesAndBuffers();
|
|
947
|
-
return;
|
|
948
|
-
}
|
|
949
|
-
|
|
950
965
|
// Execute the next command in the queue
|
|
951
966
|
commandQueueBusy = true;
|
|
952
967
|
mainHandler.post(new Runnable() {
|
|
@@ -1019,7 +1034,12 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1019
1034
|
return;
|
|
1020
1035
|
} else {
|
|
1021
1036
|
this.retrieveServicesCallbacks.addLast(callback);
|
|
1022
|
-
gatt.discoverServices();
|
|
1037
|
+
boolean started = gatt.discoverServices();
|
|
1038
|
+
if (!started) {
|
|
1039
|
+
this.retrieveServicesCallbacks.removeLastOccurrence(callback);
|
|
1040
|
+
callback.invoke("Failed to start service discovery", null);
|
|
1041
|
+
completedCommand();
|
|
1042
|
+
}
|
|
1023
1043
|
}
|
|
1024
1044
|
});
|
|
1025
1045
|
}
|
|
@@ -1029,7 +1049,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1029
1049
|
// and UUID of all characteristics instead of using
|
|
1030
1050
|
// service.getCharacteristic(characteristicUUID)
|
|
1031
1051
|
private BluetoothGattCharacteristic findReadableCharacteristic(BluetoothGattService service,
|
|
1032
|
-
|
|
1052
|
+
UUID characteristicUUID) {
|
|
1033
1053
|
|
|
1034
1054
|
if (service != null) {
|
|
1035
1055
|
int read = BluetoothGattCharacteristic.PROPERTY_READ;
|
|
@@ -1051,7 +1071,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1051
1071
|
}
|
|
1052
1072
|
|
|
1053
1073
|
private BluetoothGattCharacteristic findCharacteristic(BluetoothGattService service,
|
|
1054
|
-
|
|
1074
|
+
UUID characteristicUUID) {
|
|
1055
1075
|
|
|
1056
1076
|
if (service != null) {
|
|
1057
1077
|
return service.getCharacteristic(characteristicUUID);
|
|
@@ -1060,30 +1080,39 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1060
1080
|
return null;
|
|
1061
1081
|
}
|
|
1062
1082
|
|
|
1063
|
-
|
|
1083
|
+
private void doWrite(final BluetoothGattCharacteristic characteristic, final byte[] data) {
|
|
1084
|
+
characteristic.setValue(data);
|
|
1085
|
+
if (!gatt.writeCharacteristic(characteristic)) {
|
|
1086
|
+
// write without response, caller will handle the callback
|
|
1087
|
+
for (Callback writeCallback : writeCallbacks) {
|
|
1088
|
+
writeCallback.invoke("Write failed", null);
|
|
1089
|
+
}
|
|
1090
|
+
writeCallbacks.clear();
|
|
1091
|
+
completedCommand();
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
private boolean enqueueWrite(final BluetoothGattCharacteristic characteristic, byte[] data, final Callback callback) {
|
|
1064
1096
|
final byte[] copyOfData = copyOf(data);
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
// write without response, caller will handle the callback
|
|
1075
|
-
for (Callback writeCallback : writeCallbacks) {
|
|
1076
|
-
writeCallback.invoke("Write failed", null);
|
|
1077
|
-
}
|
|
1078
|
-
writeCallbacks.clear();
|
|
1079
|
-
completedCommand();
|
|
1097
|
+
final boolean withResponse = characteristic.getWriteType() == BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT;
|
|
1098
|
+
if (withResponse && callback != null) {
|
|
1099
|
+
writeCallbacks.addLast(callback);
|
|
1100
|
+
}
|
|
1101
|
+
return enqueue(() -> {
|
|
1102
|
+
if (!isConnected() || gatt == null) {
|
|
1103
|
+
if (withResponse && callback != null) {
|
|
1104
|
+
writeCallbacks.removeLastOccurrence(callback);
|
|
1105
|
+
callback.invoke("Device is not connected", null);
|
|
1080
1106
|
}
|
|
1107
|
+
completedCommand();
|
|
1108
|
+
return;
|
|
1081
1109
|
}
|
|
1110
|
+
doWrite(characteristic, copyOfData);
|
|
1082
1111
|
});
|
|
1083
1112
|
}
|
|
1084
1113
|
|
|
1085
1114
|
public void write(UUID serviceUUID, UUID characteristicUUID, byte[] data, Integer maxByteSize,
|
|
1086
|
-
|
|
1115
|
+
Integer queueSleepTime, Callback callback, int writeType) {
|
|
1087
1116
|
enqueue(() -> {
|
|
1088
1117
|
if (!isConnected() || gatt == null) {
|
|
1089
1118
|
callback.invoke("Device is not connected", null);
|
|
@@ -1104,12 +1133,15 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1104
1133
|
characteristic.setWriteType(writeType);
|
|
1105
1134
|
|
|
1106
1135
|
if (data.length <= maxByteSize) {
|
|
1107
|
-
if (!
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
if (BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE == writeType) {
|
|
1111
|
-
callback.invoke();
|
|
1136
|
+
if (!enqueueWrite(characteristic, data, callback)) {
|
|
1137
|
+
if (BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT == writeType) {
|
|
1138
|
+
writeCallbacks.removeLastOccurrence(callback);
|
|
1112
1139
|
}
|
|
1140
|
+
callback.invoke("Write failed");
|
|
1141
|
+
completedCommand();
|
|
1142
|
+
return;
|
|
1143
|
+
} else if (BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE == writeType) {
|
|
1144
|
+
callback.invoke();
|
|
1113
1145
|
}
|
|
1114
1146
|
} else {
|
|
1115
1147
|
int dataLength = data.length;
|
|
@@ -1134,21 +1166,24 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1134
1166
|
|
|
1135
1167
|
if (BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT == writeType) {
|
|
1136
1168
|
writeQueue.addAll(splittedMessage);
|
|
1137
|
-
if (!
|
|
1169
|
+
if (!enqueueWrite(characteristic, firstMessage, callback)) {
|
|
1138
1170
|
writeQueue.clear();
|
|
1171
|
+
writeCallbacks.remove(callback);
|
|
1139
1172
|
callback.invoke("Write failed");
|
|
1173
|
+
completedCommand();
|
|
1174
|
+
return;
|
|
1140
1175
|
}
|
|
1141
1176
|
} else {
|
|
1142
1177
|
try {
|
|
1143
1178
|
boolean writeError = false;
|
|
1144
|
-
if (!
|
|
1179
|
+
if (!enqueueWrite(characteristic, firstMessage, callback)) {
|
|
1145
1180
|
writeError = true;
|
|
1146
1181
|
callback.invoke("Write failed");
|
|
1147
1182
|
}
|
|
1148
1183
|
if (!writeError) {
|
|
1149
1184
|
Thread.sleep(queueSleepTime);
|
|
1150
1185
|
for (byte[] message : splittedMessage) {
|
|
1151
|
-
if (!
|
|
1186
|
+
if (!enqueueWrite(characteristic, message, callback)) {
|
|
1152
1187
|
writeError = true;
|
|
1153
1188
|
callback.invoke("Write failed");
|
|
1154
1189
|
break;
|
|
@@ -1159,8 +1194,14 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1159
1194
|
callback.invoke();
|
|
1160
1195
|
}
|
|
1161
1196
|
}
|
|
1197
|
+
if (writeError) {
|
|
1198
|
+
completedCommand();
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1162
1201
|
} catch (InterruptedException e) {
|
|
1163
1202
|
callback.invoke("Error during writing");
|
|
1203
|
+
completedCommand();
|
|
1204
|
+
return;
|
|
1164
1205
|
}
|
|
1165
1206
|
}
|
|
1166
1207
|
}
|
|
@@ -1234,7 +1275,7 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1234
1275
|
// and UUID of all characteristics instead of using
|
|
1235
1276
|
// service.getCharacteristic(characteristicUUID)
|
|
1236
1277
|
private BluetoothGattCharacteristic findWritableCharacteristic(BluetoothGattService service,
|
|
1237
|
-
|
|
1278
|
+
UUID characteristicUUID, int writeType) {
|
|
1238
1279
|
try {
|
|
1239
1280
|
// get write property
|
|
1240
1281
|
int writeProperty = BluetoothGattCharacteristic.PROPERTY_WRITE;
|
|
@@ -1242,9 +1283,9 @@ public class Peripheral extends BluetoothGattCallback {
|
|
|
1242
1283
|
writeProperty = BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE;
|
|
1243
1284
|
}
|
|
1244
1285
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1286
|
+
if (service == null) {
|
|
1287
|
+
throw new Exception("Service is null.");
|
|
1288
|
+
}
|
|
1248
1289
|
List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
|
|
1249
1290
|
for (BluetoothGattCharacteristic characteristic : characteristics) {
|
|
1250
1291
|
if ((characteristic.getProperties() & writeProperty) != 0
|
|
@@ -36,7 +36,7 @@ public abstract class ScanManager {
|
|
|
36
36
|
|
|
37
37
|
public abstract void stopScan(Callback callback);
|
|
38
38
|
|
|
39
|
-
public abstract void scan(
|
|
39
|
+
public abstract void scan(ReadableMap options, Callback callback);
|
|
40
40
|
|
|
41
41
|
public abstract boolean isScanning();
|
|
42
42
|
|