Skip to content

Commit 7709abe

Browse files
committed
Android: Notification queueing
1 parent 3611f41 commit 7709abe

File tree

1 file changed

+83
-5
lines changed

1 file changed

+83
-5
lines changed

src/android/BluetoothLePlugin.java

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public class BluetoothLePlugin extends CordovaPlugin {
8989
//Quick Writes
9090
private LinkedList<byte[]> queueQuick = new LinkedList<byte[]>();
9191

92+
//Peripheral queue
93+
private LinkedList<Operation> peripheralQueue = new LinkedList<Operation>();
94+
9295
//Object keys
9396
private final String keyStatus = "status";
9497
private final String keyError = "error";
@@ -127,6 +130,7 @@ public class BluetoothLePlugin extends CordovaPlugin {
127130
private final String keyConnectionPriority = "connectionPriority";
128131
private final String keyMtu = "mtu";
129132
private final String keyPin = "pin";
133+
private final String keySent = "sent";
130134
private final String keyQueue = "queue";
131135

132136
//Write Types
@@ -155,6 +159,7 @@ public class BluetoothLePlugin extends CordovaPlugin {
155159
private final String statusRssi = "rssi";
156160
private final String statusConnectionPriorityRequested = "connectionPriorityRequested";
157161
private final String statusMtu = "mtu";
162+
private final String statusNotified = "notified";
158163

159164
//Properties
160165
private final String propertyBroadcast = "broadcast";
@@ -212,6 +217,7 @@ public class BluetoothLePlugin extends CordovaPlugin {
212217
private final String errorRequestConnectionPriority = "requestConnectPriority";
213218
private final String errorMtu = "mtu";
214219
private final String errorRetrievePeripheralsByAddress = "retrievePeripheralsByAddress";
220+
private final String errorNotify = "notify";
215221

216222
//Error Messages
217223
//Initialization
@@ -414,7 +420,9 @@ public boolean execute(String action, final JSONArray args, final CallbackContex
414420
} else if ("respond".equals(action)) {
415421
respondAction(args, callbackContext);
416422
} else if ("notify".equals(action)) {
417-
notifyAction(args, callbackContext);
423+
Operation operation = new Operation("notify", args, callbackContext);
424+
peripheralQueue.add(operation);
425+
peripheralQueueStart();
418426
} else if ("setPin".equals(action)) {
419427
setPinAction(args, callbackContext);
420428
} else if ("retrievePeripheralsByAddress".equals(action)) {
@@ -822,15 +830,18 @@ private void respondAction(JSONArray args, CallbackContext callbackContext) {
822830
}
823831
}
824832

825-
private void notifyAction(JSONArray args, CallbackContext callbackContext) {
833+
private boolean notifyAction(Operation operation) {
834+
JSONArray args = operation.args;
835+
CallbackContext callbackContext = operation.callbackContext;
836+
826837
JSONObject obj = getArgsObject(args);
827838
if (isNotArgsObject(obj, callbackContext)) {
828-
return;
839+
return false;
829840
}
830841

831842
String address = getAddress(obj);
832843
if (isNotAddress(address, callbackContext)) {
833-
return;
844+
return false;
834845
}
835846
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
836847

@@ -841,6 +852,7 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
841852
addProperty(returnObj, "error", "service");
842853
addProperty(returnObj, "message", "Service not found");
843854
callbackContext.error(returnObj);
855+
return false;
844856
}
845857

846858
UUID characteristicUuid = getUUID(obj.optString("characteristic", null));
@@ -850,6 +862,7 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
850862
addProperty(returnObj, "error", "characteristic");
851863
addProperty(returnObj, "message", "Characteristic not found");
852864
callbackContext.error(returnObj);
865+
return false;
853866
}
854867

855868
byte[] value = getPropertyBytes(obj, "value");
@@ -859,6 +872,7 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
859872
addProperty(returnObj, "error", "respond");
860873
addProperty(returnObj, "message", "Failed to set value");
861874
callbackContext.error(returnObj);
875+
return false;
862876
}
863877

864878
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(clientConfigurationDescriptorUuid);
@@ -869,14 +883,16 @@ private void notifyAction(JSONArray args, CallbackContext callbackContext) {
869883
isIndicate = true;
870884
}
871885

872-
//Wait for onNotificationSent event
873886
boolean result = gattServer.notifyCharacteristicChanged(device, characteristic, isIndicate);
874887
if (!result) {
875888
JSONObject returnObj = new JSONObject();
876889
addProperty(returnObj, "error", "notify");
877890
addProperty(returnObj, "message", "Failed to notify");
878891
callbackContext.error(returnObj);
892+
return false;
879893
}
894+
895+
return true;
880896
}
881897

882898
public void hasPermissionAction(CallbackContext callbackContext) {
@@ -3243,6 +3259,38 @@ private void queueRemove(HashMap<Object, Object> connection) {
32433259
queueNext(connection);
32443260
}
32453261

3262+
private void peripheralQueueStart() {
3263+
if (peripheralQueue.size() > 1) {
3264+
return;
3265+
}
3266+
3267+
peripheralQueueNext();
3268+
}
3269+
3270+
private void peripheralQueueNext() {
3271+
Operation operation = peripheralQueue.peek();
3272+
3273+
boolean result = notifyAction(operation);
3274+
3275+
if (!result) {
3276+
peripheralQueueRemove();
3277+
}
3278+
}
3279+
3280+
private void peripheralQueueRemove() {
3281+
if (peripheralQueue.size() == 0) {
3282+
return;
3283+
}
3284+
3285+
peripheralQueue.poll();
3286+
3287+
if (peripheralQueue.size() == 0) {
3288+
return;
3289+
}
3290+
3291+
peripheralQueueNext();
3292+
}
3293+
32463294
private HashMap<Object, Object> EnsureCallback(UUID characteristicUuid, HashMap<Object, Object> connection) {
32473295
HashMap<Object, Object> characteristicCallbacks = (HashMap<Object, Object>) connection.get(characteristicUuid);
32483296

@@ -4630,6 +4678,36 @@ public void onMtuChanged(BluetoothDevice device, int mtu) {
46304678
}
46314679

46324680
public void onNotificationSent(BluetoothDevice device, int status) {
4681+
Operation operation = peripheralQueue.peek();
4682+
4683+
JSONArray args = operation.args;
4684+
CallbackContext callbackContext = operation.callbackContext;
4685+
4686+
peripheralQueueRemove();
4687+
4688+
//If no callback, just return
4689+
if (callbackContext == null) {
4690+
return;
4691+
}
4692+
4693+
JSONObject obj = getArgsObject(args);
4694+
4695+
JSONObject returnObj = new JSONObject();
4696+
4697+
addDevice(returnObj, device);
4698+
4699+
//If successfully notified, return value
4700+
if (status == BluetoothGatt.GATT_SUCCESS) {
4701+
addProperty(returnObj, keyStatus, statusNotified);
4702+
addProperty(returnObj, keySent, true);
4703+
callbackContext.success(returnObj);
4704+
} else {
4705+
//Else it failed
4706+
addProperty(returnObj, keyError, errorNotify);
4707+
callbackContext.error(returnObj);
4708+
}
4709+
4710+
//TODO: Remove code below (kept for backward compatibility)
46334711
if (initPeripheralCallback == null) {
46344712
return;
46354713
}

0 commit comments

Comments
 (0)