Skip to content

Commit 32cfa04

Browse files
fix: minor updates to peripheral shutdown and cleanup dependencies (#77)
* fix: do not access address when connectedClient is null Signed-off-by: Berend Sliedrecht <[email protected]> * chore: update dependencies Signed-off-by: Berend Sliedrecht <[email protected]> * fix: removed unused items Signed-off-by: Berend Sliedrecht <[email protected]> * chore: update dependencies to highest patch version Signed-off-by: Berend Sliedrecht <[email protected]> * feat: added hooks and context Signed-off-by: Berend Sliedrecht <[email protected]> * feat: disconnect for ios central and android peripheral Signed-off-by: Berend Sliedrecht <[email protected]> --------- Signed-off-by: Berend Sliedrecht <[email protected]>
1 parent 62922c2 commit 32cfa04

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+712
-2150
lines changed

android/src/main/java/com/reactnativebledidcomm/BleDidcommModule.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package com.reactnativebledidcomm
22

33
import androidx.annotation.RequiresPermission
4-
import com.facebook.react.bridge.*
4+
import com.facebook.react.bridge.Promise
5+
import com.facebook.react.bridge.ReactApplicationContext
6+
import com.facebook.react.bridge.ReactContextBaseJavaModule
7+
import com.facebook.react.bridge.ReactMethod
8+
import com.facebook.react.bridge.ReadableMap
59
import com.reactnativebledidcomm.central.CentralManager
610
import com.reactnativebledidcomm.central.CentralManagerException
711
import com.reactnativebledidcomm.peripheral.PeripheralManager

android/src/main/java/com/reactnativebledidcomm/central/CentralManager.kt

Lines changed: 51 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -60,50 +60,49 @@ class CentralManager(private val context: ReactContext) {
6060
var characteristicWriteUUID: UUID? = null
6161
var characteristicIndicationUUID: UUID? = null
6262

63+
private val scanSettings = ScanSettings
64+
.Builder()
65+
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
66+
.setReportDelay(0)
67+
.build()
68+
6369
fun setService(
6470
serviceUUID: UUID,
6571
writeCharacteristicUUID: UUID,
6672
indicationCharacteristicUUID: UUID,
6773
) {
6874
this.serviceUUID = serviceUUID
69-
this.characteristicWriteUUID = writeCharacteristicUUID
70-
this.characteristicIndicationUUID = indicationCharacteristicUUID
75+
characteristicWriteUUID = writeCharacteristicUUID
76+
characteristicIndicationUUID = indicationCharacteristicUUID
7177
}
7278

7379
@SuppressLint("MissingPermission")
7480
fun shutdownCentral() {
7581
try {
76-
this.stopScan()
77-
this.connectedGatt?.disconnect()
78-
this.connectedGatt?.close()
79-
} catch (e: CentralManagerException.NotScanning) {
80-
// Not Scanning
81-
} catch (e: Exception) {
82-
// Error we don't care about
82+
characteristicIndication?.let {
83+
unsubscribeFromCharacteristic(it)
84+
}
85+
stopScan()
86+
connectedGatt?.disconnect()
87+
connectedGatt?.close()
88+
} catch (_: Exception) {
8389
} finally {
84-
this.serviceUUID = null
85-
this.characteristicWriteUUID = null
86-
this.characteristicIndicationUUID = null
87-
this.connectedGatt = null
88-
this.discoveredPeripherals.clear()
90+
serviceUUID = null
91+
characteristicWriteUUID = null
92+
characteristicIndicationUUID = null
93+
connectedGatt = null
94+
discoveredPeripherals.clear()
8995
}
9096
}
9197

9298
@RequiresPermission(value = "android.permission.BLUETOOTH_SCAN")
9399
fun scan() {
94-
val serviceUUID = this.serviceUUID
95-
?: throw CentralManagerException.NoService()
96-
97-
val settings = ScanSettings
98-
.Builder()
99-
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
100-
.setReportDelay(0)
101-
.build()
100+
val serviceUUID = serviceUUID ?: throw CentralManagerException.NoService()
102101

103102
val filter = ScanFilter.Builder().setServiceUuid(ParcelUuid(serviceUUID)).build()
104103
val filters = listOf(filter)
105104

106-
bleScanner.startScan(filters, settings, scanCallback)
105+
bleScanner.startScan(filters, scanSettings, scanCallback)
107106
}
108107

109108
@RequiresPermission(value = "android.permission.BLUETOOTH_SCAN")
@@ -123,6 +122,10 @@ class CentralManager(private val context: ReactContext) {
123122
@RequiresPermission(value = "android.permission.BLUETOOTH_CONNECT")
124123
fun write(message: ByteArray) {
125124
Log.d(Constants.TAG, "[CENTRAL]: Sending message of ${message.size} bytes.")
125+
val chunkSize =
126+
min(connectedMtu - Constants.NUMBER_OF_BYTES_FOR_DATA_HEADER, message.count())
127+
Log.d(Constants.TAG, "[CENTRAL]: Using a chunk size of $chunkSize. Sending ${message.size / chunkSize + 1} messages.")
128+
126129
if (isSending) throw CentralManagerException.AlreadySending()
127130
val characteristic =
128131
characteristicWrite ?: throw CentralManagerException.NoCharacteristicFound()
@@ -138,29 +141,31 @@ class CentralManager(private val context: ReactContext) {
138141

139142
Thread {
140143
isSending = true
141-
val chunkSize =
142-
min(connectedMtu - Constants.NUMBER_OF_BYTES_FOR_DATA_HEADER, message.count())
144+
143145
for (chunkIndexStart in 0..message.count() step chunkSize) {
144146
val chunkIndexEnd = min(chunkIndexStart + chunkSize, message.count()) - 1
145147
val chunkedMessage = message.sliceArray(IntRange(chunkIndexStart, chunkIndexEnd))
148+
if (chunkedMessage.isEmpty()) {
149+
continue
150+
}
146151
characteristic.value = chunkedMessage
147152
while (!isPeripheralReady) {
148153
Thread.sleep(20)
149154
}
150155
Log.d(
151156
Constants.TAG,
152-
"[CENTRAL]: Sending chunked message of ${chunkedMessage.size} bytes."
157+
"[CENTRAL]: Sending chunked message of ${chunkedMessage.size} bytes.",
153158
)
154159
val didSend = connectedPeripheral.writeCharacteristic(characteristic)
155160
if (didSend) {
156161
Log.d(
157162
Constants.TAG,
158-
"[CENTRAL]: Send the message"
163+
"[CENTRAL]: Sent the message",
159164
)
160165
} else {
161166
Log.d(
162167
Constants.TAG,
163-
"[CENTRAL]: Did not send the message"
168+
"[CENTRAL]: Did not sent the message",
164169
)
165170
}
166171
isPeripheralReady = false
@@ -176,17 +181,11 @@ class CentralManager(private val context: ReactContext) {
176181
}
177182

178183
@SuppressLint("MissingPermission")
179-
private fun subscribeToIndication(
180-
characteristic: BluetoothGattCharacteristic,
181-
gatt: BluetoothGatt
182-
) {
184+
private fun subscribeToIndications(characteristic: BluetoothGattCharacteristic, gatt: BluetoothGatt) {
183185
val cccdUuid = UUID.fromString(Constants.CCC_DESCRIPTOR_UUID)
184186
characteristic.getDescriptor(cccdUuid)?.let { cccDescriptor ->
185187
if (!gatt.setCharacteristicNotification(characteristic, true)) {
186-
Log.e(
187-
Constants.TAG,
188-
"[CENTRAL]: Could not set notifications for characteristic ${characteristic.uuid}"
189-
)
188+
Log.e(Constants.TAG, "[CENTRAL]: setNotification(true) failed for ${characteristic.uuid}")
190189
return
191190
}
192191
cccDescriptor.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
@@ -201,10 +200,7 @@ class CentralManager(private val context: ReactContext) {
201200
val cccdUuid = UUID.fromString(Constants.CCC_DESCRIPTOR_UUID)
202201
characteristic.getDescriptor(cccdUuid)?.let { cccDescriptor ->
203202
if (!gatt.setCharacteristicNotification(characteristic, false)) {
204-
Log.e(
205-
Constants.TAG,
206-
"[CENTRAL]: Could not unsubscribe from characteristic ${characteristic.uuid}"
207-
)
203+
Log.e(Constants.TAG, "[CENTRAL]: setNotification(false) failed for ${characteristic.uuid}")
208204
return
209205
}
210206
cccDescriptor.value = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
@@ -220,17 +216,16 @@ class CentralManager(private val context: ReactContext) {
220216
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
221217
Log.d(
222218
Constants.TAG,
223-
"[CENTRAL]: Connection state has been changed to $newState with status $status"
219+
"[CENTRAL]: Connection state has been changed to $newState with status $status",
224220
)
225221

226222
if (status == BluetoothGatt.GATT_SUCCESS) {
227223
val params = Arguments.createMap().apply {
228224
putString("identifier", gatt.device.address)
229225
}
230226
if (newState == BluetoothProfile.STATE_CONNECTED) {
231-
gatt.requestMtu(512)
227+
gatt.discoverServices()
232228
stopScan()
233-
sendEvent(BleDidcommEvent.OnConnectedPeripheral, params)
234229
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
235230
sendEvent(BleDidcommEvent.OnDisconnectedPeripheral, params)
236231
gatt.close()
@@ -266,20 +261,11 @@ class CentralManager(private val context: ReactContext) {
266261
return
267262
}
268263

269-
gatt.setCharacteristicNotification(characteristicIndication, true)
270-
val descriptor =
271-
characteristicIndication?.getDescriptor(UUID.fromString(Constants.CCC_DESCRIPTOR_UUID))
272-
?: run {
273-
Log.d(
274-
Constants.TAG,
275-
"[CENTRAL]: Indication Descriptor not found. Make sure CCC is set on the descriptor. Task of the peripheral"
276-
)
277-
gatt.disconnect()
278-
return
279-
}
280-
281-
descriptor.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
282-
gatt.writeDescriptor(descriptor)
264+
characteristicIndication?.let {
265+
subscribeToIndications(it, gatt)
266+
} ?: run {
267+
Log.e(Constants.TAG, "[CENTRAL]: characteristic not found $characteristicIndicationUUID")
268+
}
283269
}
284270

285271
// Triggered when the client is ready to send the next message
@@ -301,7 +287,7 @@ class CentralManager(private val context: ReactContext) {
301287
) {
302288
Log.d(
303289
Constants.TAG,
304-
"[CENTRAL]: Received an indication of ${characteristic.value.size} bytes."
290+
"[CENTRAL]: Received an indication of ${characteristic.value.size} bytes.",
305291
)
306292

307293
if (characteristic.uuid == characteristicIndicationUUID) {
@@ -320,13 +306,19 @@ class CentralManager(private val context: ReactContext) {
320306
}
321307
}
322308

309+
@SuppressLint("MissingPermission")
323310
override fun onDescriptorWrite(
324311
gatt: BluetoothGatt,
325312
descriptor: BluetoothGattDescriptor,
326-
status: Int
313+
status: Int,
327314
) {
328315
super.onDescriptorWrite(gatt, descriptor, status)
329316
Log.d(Constants.TAG, "[CENTRAL]: Descriptor write. Connection is ready")
317+
gatt.requestMtu(512)
318+
val params = Arguments.createMap().apply {
319+
putString("identifier", gatt.device.address)
320+
}
321+
sendEvent(BleDidcommEvent.OnConnectedPeripheral, params)
330322
}
331323

332324
// Triggered when the MTU has been changed.
@@ -339,7 +331,6 @@ class CentralManager(private val context: ReactContext) {
339331
return
340332
}
341333
connectedMtu = mtu
342-
gatt.discoverServices()
343334
}
344335
}
345336

@@ -348,7 +339,6 @@ class CentralManager(private val context: ReactContext) {
348339
override fun onScanResult(callbackType: Int, result: ScanResult) {
349340
val name = result.scanRecord?.deviceName ?: result.device.name ?: result.device.address
350341
Log.d(Constants.TAG, "[CENTRAL]: Found item $name")
351-
super.onScanResult(callbackType, result)
352342

353343
discoveredPeripherals.add(result.device)
354344
val params = Arguments.createMap().apply {
@@ -358,40 +348,3 @@ class CentralManager(private val context: ReactContext) {
358348
}
359349
}
360350
}
361-
362-
363-
364-
365-
366-
367-
368-
369-
370-
371-
372-
373-
374-
375-
376-
377-
378-
379-
380-
381-
382-
383-
384-
385-
386-
387-
388-
389-
390-
391-
392-
393-
394-
395-
396-
397-

0 commit comments

Comments
 (0)