@capacitor-community/bluetooth-le 3.0.1 → 3.1.0
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/README.md +46 -8
- package/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/BluetoothLe.kt +13 -3
- package/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/Device.kt +127 -21
- package/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/DeviceScanner.kt +2 -0
- package/dist/docs.json +27 -6
- package/dist/esm/bleClient.d.ts +12 -6
- package/dist/esm/bleClient.js +7 -2
- package/dist/esm/bleClient.js.map +1 -1
- package/dist/esm/definitions.d.ts +2 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +1 -0
- package/dist/esm/web.js +3 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +10 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +10 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/DeviceManager.swift +7 -2
- package/ios/Plugin/Plugin.m +1 -0
- package/ios/Plugin/Plugin.swift +4 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<a href="https://www.npmjs.com/package/@capacitor-community/bluetooth-le"><img src="https://img.shields.io/npm/dw/@capacitor-community/bluetooth-le?style=flat-square" /></a>
|
|
14
14
|
<a href="https://www.npmjs.com/package/@capacitor-community/bluetooth-le"><img src="https://img.shields.io/npm/v/@capacitor-community/bluetooth-le?style=flat-square" /></a>
|
|
15
15
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
16
|
-
<a href="#contributors-"><img src="https://img.shields.io/badge/all%20contributors-
|
|
16
|
+
<a href="#contributors-"><img src="https://img.shields.io/badge/all%20contributors-14-orange?style=flat-square" /></a>
|
|
17
17
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
18
18
|
</p>
|
|
19
19
|
|
|
@@ -51,6 +51,7 @@ Below is an index of all the methods available.
|
|
|
51
51
|
|
|
52
52
|
- [`initialize(...)`](#initialize)
|
|
53
53
|
- [`isEnabled()`](#isenabled)
|
|
54
|
+
- [`requestEnable()`](#requestenable)
|
|
54
55
|
- [`enable()`](#enable)
|
|
55
56
|
- [`disable()`](#disable)
|
|
56
57
|
- [`startEnabledNotifications(...)`](#startenablednotifications)
|
|
@@ -207,6 +208,8 @@ import { BleClient } from '@capacitor-community/bluetooth-le';
|
|
|
207
208
|
import { BluetoothLe } from '@capacitor-community/bluetooth-le';
|
|
208
209
|
```
|
|
209
210
|
|
|
211
|
+
### Heart rate monitor
|
|
212
|
+
|
|
210
213
|
Here is an example of how to use the plugin. It shows how to read the heart rate from a BLE heart rate monitor such as the Polar H10.
|
|
211
214
|
|
|
212
215
|
```typescript
|
|
@@ -279,7 +282,9 @@ function parseHeartRate(value: DataView): number {
|
|
|
279
282
|
}
|
|
280
283
|
```
|
|
281
284
|
|
|
282
|
-
|
|
285
|
+
### Scanning API
|
|
286
|
+
|
|
287
|
+
Here is an example of using the scanning API.
|
|
283
288
|
|
|
284
289
|
```typescript
|
|
285
290
|
import { BleClient, numberToUUID } from '@capacitor-community/bluetooth-le';
|
|
@@ -323,6 +328,7 @@ _Note_: web support depends on the browser, see [implementation status](https://
|
|
|
323
328
|
| -------------------------------------------------------------- | :-----: | :-: | :-: |
|
|
324
329
|
| [`initialize()`](#initialize) | ✅ | ✅ | ✅ |
|
|
325
330
|
| [`isEnabled()`](#isenabled) | ✅ | ✅ | -- |
|
|
331
|
+
| [`requestEnable()`](#requestEnable) | ✅ | ❌ | ❌ |
|
|
326
332
|
| [`enable()`](#enable) | ✅ | ❌ | ❌ |
|
|
327
333
|
| [`disable()`](#disable) | ✅ | ❌ | ❌ |
|
|
328
334
|
| [`startEnabledNotifications(...)`](#startenablednotifications) | ✅ | ✅ | -- |
|
|
@@ -395,6 +401,17 @@ Always returns `true` on **web**.
|
|
|
395
401
|
|
|
396
402
|
---
|
|
397
403
|
|
|
404
|
+
### requestEnable()
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
requestEnable() => Promise<void>
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
Request enabling Bluetooth. Show a system activity that allows the user to turn on Bluetooth. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#ACTION_REQUEST_ENABLE
|
|
411
|
+
Only available on **Android**.
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
398
415
|
### enable()
|
|
399
416
|
|
|
400
417
|
```typescript
|
|
@@ -403,7 +420,7 @@ enable() => Promise<void>
|
|
|
403
420
|
|
|
404
421
|
Enable Bluetooth.
|
|
405
422
|
Only available on **Android**.
|
|
406
|
-
|
|
423
|
+
**Deprecated** Will fail on Android SDK >= 33. Use `requestEnable` instead. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()
|
|
407
424
|
|
|
408
425
|
---
|
|
409
426
|
|
|
@@ -415,7 +432,7 @@ disable() => Promise<void>
|
|
|
415
432
|
|
|
416
433
|
Disable Bluetooth.
|
|
417
434
|
Only available on **Android**.
|
|
418
|
-
|
|
435
|
+
**Deprecated** Will fail on Android SDK >= 33. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()
|
|
419
436
|
|
|
420
437
|
---
|
|
421
438
|
|
|
@@ -608,15 +625,16 @@ Connect to a peripheral BLE device. For an example, see [usage](#usage).
|
|
|
608
625
|
### createBond(...)
|
|
609
626
|
|
|
610
627
|
```typescript
|
|
611
|
-
createBond(deviceId: string) => Promise<void>
|
|
628
|
+
createBond(deviceId: string, options?: TimeoutOptions | undefined) => Promise<void>
|
|
612
629
|
```
|
|
613
630
|
|
|
614
631
|
Create a bond with a peripheral BLE device.
|
|
615
632
|
Only available on **Android**. On iOS bonding is handled by the OS.
|
|
616
633
|
|
|
617
|
-
| Param | Type
|
|
618
|
-
| -------------- |
|
|
619
|
-
| **`deviceId`** | <code>string</code>
|
|
634
|
+
| Param | Type | Description |
|
|
635
|
+
| -------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
636
|
+
| **`deviceId`** | <code>string</code> | The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
|
|
637
|
+
| **`options`** | <code><a href="#timeoutoptions">TimeoutOptions</a></code> | Options for plugin call |
|
|
620
638
|
|
|
621
639
|
---
|
|
622
640
|
|
|
@@ -1046,6 +1064,23 @@ await BleClient.disconnect(device.deviceId);
|
|
|
1046
1064
|
await BleClient.connect(device.deviceId);
|
|
1047
1065
|
```
|
|
1048
1066
|
|
|
1067
|
+
#### No devices found on Android
|
|
1068
|
+
|
|
1069
|
+
On Android, the `initialize` call requests the location permission. However, if location services are disable on the OS level, the app will not find any devices. You can check if the location is enabled and open the settings when not.
|
|
1070
|
+
|
|
1071
|
+
```typescript
|
|
1072
|
+
async function initialize() {
|
|
1073
|
+
// Check if location is enabled
|
|
1074
|
+
if (this.platform.is('android')) {
|
|
1075
|
+
const isLocationEnabled = await BleClient.isLocationEnabled();
|
|
1076
|
+
if (!isLocationEnabled) {
|
|
1077
|
+
await BleClient.openLocationSettings();
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
await BleClient.initialize();
|
|
1081
|
+
}
|
|
1082
|
+
```
|
|
1083
|
+
|
|
1049
1084
|
## Contributors ✨
|
|
1050
1085
|
|
|
1051
1086
|
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
@@ -1069,6 +1104,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
1069
1104
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/aadito123"><img src="https://avatars.githubusercontent.com/u/63646058?v=4?s=100" width="100px;" alt="Aadit Olkar"/><br /><sub><b>Aadit Olkar</b></sub></a><br /><a href="https://github.com/capacitor-community/bluetooth-le/commits?author=aadito123" title="Code">💻</a></td>
|
|
1070
1105
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/y3nd"><img src="https://avatars.githubusercontent.com/u/18102153?v=4?s=100" width="100px;" alt="Yoann N."/><br /><sub><b>Yoann N.</b></sub></a><br /><a href="https://github.com/capacitor-community/bluetooth-le/commits?author=y3nd" title="Code">💻</a></td>
|
|
1071
1106
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Andy3189"><img src="https://avatars.githubusercontent.com/u/2084016?v=4?s=100" width="100px;" alt="Andy3189"/><br /><sub><b>Andy3189</b></sub></a><br /><a href="https://github.com/capacitor-community/bluetooth-le/commits?author=Andy3189" title="Code">💻</a></td>
|
|
1107
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RFM69CW"><img src="https://avatars.githubusercontent.com/u/20404734?v=4?s=100" width="100px;" alt="Sammy"/><br /><sub><b>Sammy</b></sub></a><br /><a href="https://github.com/capacitor-community/bluetooth-le/commits?author=RFM69CW" title="Documentation">📖</a></td>
|
|
1108
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/td-tomasz-joniec"><img src="https://avatars.githubusercontent.com/u/109506928?v=4?s=100" width="100px;" alt="td-tomasz-joniec"/><br /><sub><b>td-tomasz-joniec</b></sub></a><br /><a href="https://github.com/capacitor-community/bluetooth-le/commits?author=td-tomasz-joniec" title="Code">💻</a></td>
|
|
1109
|
+
<td align="center" valign="top" width="14.28%"><a href="https://fanxj.com"><img src="https://avatars.githubusercontent.com/u/10436013?v=4?s=100" width="100px;" alt="Michele Ferrari"/><br /><sub><b>Michele Ferrari</b></sub></a><br /><a href="https://github.com/capacitor-community/bluetooth-le/commits?author=micheleypf" title="Code">💻</a></td>
|
|
1072
1110
|
</tr>
|
|
1073
1111
|
</tbody>
|
|
1074
1112
|
</table>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
package com.capacitorjs.community.plugins.bluetoothle
|
|
2
2
|
|
|
3
3
|
import android.Manifest
|
|
4
|
+
import android.annotation.SuppressLint
|
|
4
5
|
import android.bluetooth.BluetoothAdapter
|
|
6
|
+
import android.bluetooth.BluetoothAdapter.ACTION_REQUEST_ENABLE
|
|
5
7
|
import android.bluetooth.BluetoothDevice
|
|
6
8
|
import android.bluetooth.BluetoothGatt
|
|
7
9
|
import android.bluetooth.BluetoothGattCharacteristic
|
|
@@ -36,6 +38,7 @@ import com.getcapacitor.annotation.PermissionCallback
|
|
|
36
38
|
import java.util.UUID
|
|
37
39
|
|
|
38
40
|
|
|
41
|
+
@SuppressLint("MissingPermission")
|
|
39
42
|
@CapacitorPlugin(
|
|
40
43
|
name = "BluetoothLe",
|
|
41
44
|
permissions = [
|
|
@@ -96,8 +99,7 @@ class BluetoothLe : Plugin() {
|
|
|
96
99
|
|
|
97
100
|
@PluginMethod
|
|
98
101
|
fun initialize(call: PluginCall) {
|
|
99
|
-
|
|
100
|
-
if (Build.VERSION.SDK_INT >= 31) {
|
|
102
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
101
103
|
val neverForLocation = call.getBoolean("androidNeverForLocation", false) as Boolean
|
|
102
104
|
aliases = if (neverForLocation) {
|
|
103
105
|
arrayOf(
|
|
@@ -160,6 +162,13 @@ class BluetoothLe : Plugin() {
|
|
|
160
162
|
call.resolve(result)
|
|
161
163
|
}
|
|
162
164
|
|
|
165
|
+
@PluginMethod
|
|
166
|
+
fun requestEnable(call: PluginCall) {
|
|
167
|
+
val intent = Intent(ACTION_REQUEST_ENABLE)
|
|
168
|
+
activity.startActivity(intent)
|
|
169
|
+
call.resolve()
|
|
170
|
+
}
|
|
171
|
+
|
|
163
172
|
@PluginMethod
|
|
164
173
|
fun enable(call: PluginCall) {
|
|
165
174
|
assertBluetoothAdapter(call) ?: return
|
|
@@ -439,7 +448,8 @@ class BluetoothLe : Plugin() {
|
|
|
439
448
|
@PluginMethod
|
|
440
449
|
fun createBond(call: PluginCall) {
|
|
441
450
|
val device = getOrCreateDevice(call) ?: return
|
|
442
|
-
|
|
451
|
+
val timeout = call.getFloat("timeout", DEFAULT_TIMEOUT)!!.toLong()
|
|
452
|
+
device.createBond(timeout) { response ->
|
|
443
453
|
run {
|
|
444
454
|
if (response.success) {
|
|
445
455
|
call.resolve()
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package com.capacitorjs.community.plugins.bluetoothle
|
|
2
2
|
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.annotation.TargetApi
|
|
3
5
|
import android.bluetooth.BluetoothAdapter
|
|
4
6
|
import android.bluetooth.BluetoothDevice
|
|
5
7
|
import android.bluetooth.BluetoothGatt
|
|
@@ -8,6 +10,7 @@ import android.bluetooth.BluetoothGattCharacteristic
|
|
|
8
10
|
import android.bluetooth.BluetoothGattDescriptor
|
|
9
11
|
import android.bluetooth.BluetoothGattService
|
|
10
12
|
import android.bluetooth.BluetoothProfile
|
|
13
|
+
import android.bluetooth.BluetoothStatusCodes
|
|
11
14
|
import android.content.BroadcastReceiver
|
|
12
15
|
import android.content.Context
|
|
13
16
|
import android.content.Intent
|
|
@@ -15,6 +18,7 @@ import android.content.IntentFilter
|
|
|
15
18
|
import android.os.Build
|
|
16
19
|
import android.os.Handler
|
|
17
20
|
import android.os.Looper
|
|
21
|
+
import androidx.annotation.RequiresApi
|
|
18
22
|
import com.getcapacitor.Logger
|
|
19
23
|
import java.util.UUID
|
|
20
24
|
import java.util.concurrent.ConcurrentLinkedQueue
|
|
@@ -43,6 +47,7 @@ fun <T> ConcurrentLinkedQueue<T>.popFirstMatch(predicate: (T) -> Boolean): T? {
|
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
@SuppressLint("MissingPermission")
|
|
46
51
|
class Device(
|
|
47
52
|
private val context: Context,
|
|
48
53
|
bluetoothAdapter: BluetoothAdapter,
|
|
@@ -123,9 +128,15 @@ class Device(
|
|
|
123
128
|
}
|
|
124
129
|
}
|
|
125
130
|
|
|
131
|
+
@TargetApi(Build.VERSION_CODES.S_V2)
|
|
126
132
|
override fun onCharacteristicRead(
|
|
127
133
|
gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int
|
|
128
134
|
) {
|
|
135
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
136
|
+
// handled by new callback below
|
|
137
|
+
return
|
|
138
|
+
}
|
|
139
|
+
Logger.verbose(TAG, "Using deprecated onCharacteristicRead.")
|
|
129
140
|
super.onCharacteristicRead(gatt, characteristic, status)
|
|
130
141
|
val key = "read|${characteristic.service.uuid}|${characteristic.uuid}"
|
|
131
142
|
if (status == BluetoothGatt.GATT_SUCCESS) {
|
|
@@ -141,6 +152,24 @@ class Device(
|
|
|
141
152
|
}
|
|
142
153
|
}
|
|
143
154
|
|
|
155
|
+
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
156
|
+
override fun onCharacteristicRead(
|
|
157
|
+
gatt: BluetoothGatt,
|
|
158
|
+
characteristic: BluetoothGattCharacteristic,
|
|
159
|
+
data: ByteArray,
|
|
160
|
+
status: Int
|
|
161
|
+
) {
|
|
162
|
+
Logger.verbose(TAG, "Using onCharacteristicRead from API level 33.")
|
|
163
|
+
super.onCharacteristicRead(gatt, characteristic, data, status)
|
|
164
|
+
val key = "read|${characteristic.service.uuid}|${characteristic.uuid}"
|
|
165
|
+
if (status == BluetoothGatt.GATT_SUCCESS) {
|
|
166
|
+
val value = bytesToString(data)
|
|
167
|
+
resolve(key, value)
|
|
168
|
+
} else {
|
|
169
|
+
reject(key, "Reading characteristic failed.")
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
144
173
|
override fun onCharacteristicWrite(
|
|
145
174
|
gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, status: Int
|
|
146
175
|
) {
|
|
@@ -154,9 +183,15 @@ class Device(
|
|
|
154
183
|
|
|
155
184
|
}
|
|
156
185
|
|
|
186
|
+
@TargetApi(Build.VERSION_CODES.S_V2)
|
|
157
187
|
override fun onCharacteristicChanged(
|
|
158
188
|
gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic
|
|
159
189
|
) {
|
|
190
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
191
|
+
// handled by new callback below
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
Logger.verbose(TAG, "Using deprecated onCharacteristicChanged.")
|
|
160
195
|
super.onCharacteristicChanged(gatt, characteristic)
|
|
161
196
|
val notifyKey = "notification|${characteristic.service.uuid}|${characteristic.uuid}"
|
|
162
197
|
val data = characteristic.value
|
|
@@ -166,9 +201,26 @@ class Device(
|
|
|
166
201
|
}
|
|
167
202
|
}
|
|
168
203
|
|
|
204
|
+
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
205
|
+
override fun onCharacteristicChanged(
|
|
206
|
+
gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, data: ByteArray
|
|
207
|
+
) {
|
|
208
|
+
Logger.verbose(TAG, "Using onCharacteristicChanged from API level 33.")
|
|
209
|
+
super.onCharacteristicChanged(gatt, characteristic, data)
|
|
210
|
+
val notifyKey = "notification|${characteristic.service.uuid}|${characteristic.uuid}"
|
|
211
|
+
val value = bytesToString(data)
|
|
212
|
+
callbackMap[notifyKey]?.invoke(CallbackResponse(true, value))
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@TargetApi(Build.VERSION_CODES.S_V2)
|
|
169
216
|
override fun onDescriptorRead(
|
|
170
217
|
gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int
|
|
171
218
|
) {
|
|
219
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
220
|
+
// handled by new callback below
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
Logger.verbose(TAG, "Using deprecated onDescriptorRead.")
|
|
172
224
|
super.onDescriptorRead(gatt, descriptor, status)
|
|
173
225
|
val key =
|
|
174
226
|
"readDescriptor|${descriptor.characteristic.service.uuid}|${descriptor.characteristic.uuid}|${descriptor.uuid}"
|
|
@@ -185,6 +237,22 @@ class Device(
|
|
|
185
237
|
}
|
|
186
238
|
}
|
|
187
239
|
|
|
240
|
+
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
|
|
241
|
+
override fun onDescriptorRead(
|
|
242
|
+
gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, data: ByteArray
|
|
243
|
+
) {
|
|
244
|
+
Logger.verbose(TAG, "Using onDescriptorRead from API level 33.")
|
|
245
|
+
super.onDescriptorRead(gatt, descriptor, status, data)
|
|
246
|
+
val key =
|
|
247
|
+
"readDescriptor|${descriptor.characteristic.service.uuid}|${descriptor.characteristic.uuid}|${descriptor.uuid}"
|
|
248
|
+
if (status == BluetoothGatt.GATT_SUCCESS) {
|
|
249
|
+
val value = bytesToString(data)
|
|
250
|
+
resolve(key, value)
|
|
251
|
+
} else {
|
|
252
|
+
reject(key, "Reading descriptor failed.")
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
188
256
|
override fun onDescriptorWrite(
|
|
189
257
|
gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int
|
|
190
258
|
) {
|
|
@@ -256,7 +324,7 @@ class Device(
|
|
|
256
324
|
return bluetoothGatt?.requestConnectionPriority(connectionPriority) ?: false
|
|
257
325
|
}
|
|
258
326
|
|
|
259
|
-
fun createBond(callback: (CallbackResponse) -> Unit) {
|
|
327
|
+
fun createBond(timeout: Long, callback: (CallbackResponse) -> Unit) {
|
|
260
328
|
val key = "createBond"
|
|
261
329
|
callbackMap[key] = callback
|
|
262
330
|
try {
|
|
@@ -277,6 +345,7 @@ class Device(
|
|
|
277
345
|
return
|
|
278
346
|
}
|
|
279
347
|
// otherwise, wait for bond state change
|
|
348
|
+
setTimeout(key, "Bonding timeout.", timeout)
|
|
280
349
|
}
|
|
281
350
|
|
|
282
351
|
private fun createBondStateReceiver() {
|
|
@@ -287,7 +356,14 @@ class Device(
|
|
|
287
356
|
if (action == BluetoothDevice.ACTION_BOND_STATE_CHANGED) {
|
|
288
357
|
val key = "createBond"
|
|
289
358
|
val updatedDevice =
|
|
290
|
-
|
|
359
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
360
|
+
intent.getParcelableExtra(
|
|
361
|
+
BluetoothDevice.EXTRA_DEVICE,
|
|
362
|
+
BluetoothDevice::class.java
|
|
363
|
+
)
|
|
364
|
+
} else {
|
|
365
|
+
intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
|
|
366
|
+
}
|
|
291
367
|
// BroadcastReceiver receives bond state updates from all devices, need to filter by device
|
|
292
368
|
if (device.address == updatedDevice?.address) {
|
|
293
369
|
val bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)
|
|
@@ -415,12 +491,21 @@ class Device(
|
|
|
415
491
|
return
|
|
416
492
|
}
|
|
417
493
|
val bytes = stringToBytes(value)
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
494
|
+
|
|
495
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
496
|
+
val statusCode = bluetoothGatt?.writeCharacteristic(characteristic, bytes, writeType)
|
|
497
|
+
if (statusCode != BluetoothStatusCodes.SUCCESS) {
|
|
498
|
+
reject(key, "Writing characteristic failed with status code $statusCode.")
|
|
499
|
+
return
|
|
500
|
+
}
|
|
501
|
+
} else {
|
|
502
|
+
characteristic.value = bytes
|
|
503
|
+
characteristic.writeType = writeType
|
|
504
|
+
val result = bluetoothGatt?.writeCharacteristic(characteristic)
|
|
505
|
+
if (result != true) {
|
|
506
|
+
reject(key, "Writing characteristic failed.")
|
|
507
|
+
return
|
|
508
|
+
}
|
|
424
509
|
}
|
|
425
510
|
setTimeout(key, "Write timeout.", timeout)
|
|
426
511
|
}
|
|
@@ -457,20 +542,32 @@ class Device(
|
|
|
457
542
|
return
|
|
458
543
|
}
|
|
459
544
|
|
|
460
|
-
if (enable) {
|
|
545
|
+
val value = if (enable) {
|
|
461
546
|
if ((characteristic.properties and BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) {
|
|
462
|
-
|
|
547
|
+
BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
|
463
548
|
} else if ((characteristic.properties and BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
|
|
464
|
-
|
|
549
|
+
BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
|
|
550
|
+
} else {
|
|
551
|
+
BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
|
|
465
552
|
}
|
|
466
553
|
} else {
|
|
467
|
-
|
|
554
|
+
BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE
|
|
468
555
|
}
|
|
469
556
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
557
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
558
|
+
val statusCode = bluetoothGatt?.writeDescriptor(descriptor, value)
|
|
559
|
+
if (statusCode != BluetoothStatusCodes.SUCCESS) {
|
|
560
|
+
reject(key, "Setting notification failed with status code $statusCode.")
|
|
561
|
+
return
|
|
562
|
+
}
|
|
563
|
+
} else {
|
|
564
|
+
descriptor.value = value
|
|
565
|
+
val resultDesc = bluetoothGatt?.writeDescriptor(descriptor)
|
|
566
|
+
if (resultDesc != true) {
|
|
567
|
+
reject(key, "Setting notification failed.")
|
|
568
|
+
return
|
|
569
|
+
}
|
|
570
|
+
|
|
474
571
|
}
|
|
475
572
|
// wait for onDescriptorWrite
|
|
476
573
|
}
|
|
@@ -525,11 +622,20 @@ class Device(
|
|
|
525
622
|
return
|
|
526
623
|
}
|
|
527
624
|
val bytes = stringToBytes(value)
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
625
|
+
|
|
626
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
627
|
+
val statusCode = bluetoothGatt?.writeDescriptor(descriptor, bytes)
|
|
628
|
+
if (statusCode != BluetoothStatusCodes.SUCCESS) {
|
|
629
|
+
reject(key, "Writing descriptor failed with status code $statusCode.")
|
|
630
|
+
return
|
|
631
|
+
}
|
|
632
|
+
} else {
|
|
633
|
+
descriptor.value = bytes
|
|
634
|
+
val result = bluetoothGatt?.writeDescriptor(descriptor)
|
|
635
|
+
if (result != true) {
|
|
636
|
+
reject(key, "Writing descriptor failed.")
|
|
637
|
+
return
|
|
638
|
+
}
|
|
533
639
|
}
|
|
534
640
|
setTimeout(key, "Write timeout.", timeout)
|
|
535
641
|
}
|
package/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/DeviceScanner.kt
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.capacitorjs.community.plugins.bluetoothle
|
|
2
2
|
|
|
3
|
+
import android.annotation.SuppressLint
|
|
3
4
|
import android.app.AlertDialog
|
|
4
5
|
import android.bluetooth.BluetoothAdapter
|
|
5
6
|
import android.bluetooth.BluetoothDevice
|
|
@@ -27,6 +28,7 @@ class DisplayStrings(
|
|
|
27
28
|
val noDeviceFound: String,
|
|
28
29
|
)
|
|
29
30
|
|
|
31
|
+
@SuppressLint("MissingPermission")
|
|
30
32
|
class DeviceScanner(
|
|
31
33
|
private val context: Context,
|
|
32
34
|
bluetoothAdapter: BluetoothAdapter,
|
package/dist/docs.json
CHANGED
|
@@ -33,6 +33,16 @@
|
|
|
33
33
|
"complexTypes": [],
|
|
34
34
|
"slug": "isenabled"
|
|
35
35
|
},
|
|
36
|
+
{
|
|
37
|
+
"name": "requestEnable",
|
|
38
|
+
"signature": "() => Promise<void>",
|
|
39
|
+
"parameters": [],
|
|
40
|
+
"returns": "Promise<void>",
|
|
41
|
+
"tags": [],
|
|
42
|
+
"docs": "Request enabling Bluetooth. Show a system activity that allows the user to turn on Bluetooth. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#ACTION_REQUEST_ENABLE\nOnly available on **Android**.",
|
|
43
|
+
"complexTypes": [],
|
|
44
|
+
"slug": "requestenable"
|
|
45
|
+
},
|
|
36
46
|
{
|
|
37
47
|
"name": "enable",
|
|
38
48
|
"signature": "() => Promise<void>",
|
|
@@ -41,10 +51,10 @@
|
|
|
41
51
|
"tags": [
|
|
42
52
|
{
|
|
43
53
|
"name": "deprecated",
|
|
44
|
-
"text": "See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()"
|
|
54
|
+
"text": "Will fail on Android SDK >= 33. Use `requestEnable` instead. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()"
|
|
45
55
|
}
|
|
46
56
|
],
|
|
47
|
-
"docs": "Enable Bluetooth.\nOnly available on **Android**.\n
|
|
57
|
+
"docs": "Enable Bluetooth.\nOnly available on **Android**.\n**Deprecated** Will fail on Android SDK >= 33. Use `requestEnable` instead. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()",
|
|
48
58
|
"complexTypes": [],
|
|
49
59
|
"slug": "enable"
|
|
50
60
|
},
|
|
@@ -56,10 +66,10 @@
|
|
|
56
66
|
"tags": [
|
|
57
67
|
{
|
|
58
68
|
"name": "deprecated",
|
|
59
|
-
"text": "See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()"
|
|
69
|
+
"text": "Will fail on Android SDK >= 33. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()"
|
|
60
70
|
}
|
|
61
71
|
],
|
|
62
|
-
"docs": "Disable Bluetooth.\nOnly available on **Android**.\n
|
|
72
|
+
"docs": "Disable Bluetooth.\nOnly available on **Android**.\n**Deprecated** Will fail on Android SDK >= 33. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()",
|
|
63
73
|
"complexTypes": [],
|
|
64
74
|
"slug": "disable"
|
|
65
75
|
},
|
|
@@ -313,12 +323,17 @@
|
|
|
313
323
|
},
|
|
314
324
|
{
|
|
315
325
|
"name": "createBond",
|
|
316
|
-
"signature": "(deviceId: string) => Promise<void>",
|
|
326
|
+
"signature": "(deviceId: string, options?: TimeoutOptions | undefined) => Promise<void>",
|
|
317
327
|
"parameters": [
|
|
318
328
|
{
|
|
319
329
|
"name": "deviceId",
|
|
320
330
|
"docs": "The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan))",
|
|
321
331
|
"type": "string"
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"name": "options",
|
|
335
|
+
"docs": "Options for plugin call",
|
|
336
|
+
"type": "TimeoutOptions | undefined"
|
|
322
337
|
}
|
|
323
338
|
],
|
|
324
339
|
"returns": "Promise<void>",
|
|
@@ -326,10 +341,16 @@
|
|
|
326
341
|
{
|
|
327
342
|
"name": "param",
|
|
328
343
|
"text": "deviceId The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan))"
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"name": "param",
|
|
347
|
+
"text": "options Options for plugin call"
|
|
329
348
|
}
|
|
330
349
|
],
|
|
331
350
|
"docs": "Create a bond with a peripheral BLE device.\nOnly available on **Android**. On iOS bonding is handled by the OS.",
|
|
332
|
-
"complexTypes": [
|
|
351
|
+
"complexTypes": [
|
|
352
|
+
"TimeoutOptions"
|
|
353
|
+
],
|
|
333
354
|
"slug": "createbond"
|
|
334
355
|
},
|
|
335
356
|
{
|
package/dist/esm/bleClient.d.ts
CHANGED
|
@@ -12,18 +12,22 @@ export interface BleClientInterface {
|
|
|
12
12
|
* Always returns `true` on **web**.
|
|
13
13
|
*/
|
|
14
14
|
isEnabled(): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Request enabling Bluetooth. Show a system activity that allows the user to turn on Bluetooth. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#ACTION_REQUEST_ENABLE
|
|
17
|
+
* Only available on **Android**.*/
|
|
18
|
+
requestEnable(): Promise<void>;
|
|
15
19
|
/**
|
|
16
20
|
* Enable Bluetooth.
|
|
17
21
|
* Only available on **Android**.
|
|
18
|
-
*
|
|
19
|
-
* @deprecated See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()
|
|
22
|
+
* **Deprecated** Will fail on Android SDK >= 33. Use `requestEnable` instead. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()
|
|
23
|
+
* @deprecated Will fail on Android SDK >= 33. Use `requestEnable` instead. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#enable()
|
|
20
24
|
*/
|
|
21
25
|
enable(): Promise<void>;
|
|
22
26
|
/**
|
|
23
27
|
* Disable Bluetooth.
|
|
24
28
|
* Only available on **Android**.
|
|
25
|
-
*
|
|
26
|
-
* @deprecated See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()
|
|
29
|
+
* **Deprecated** Will fail on Android SDK >= 33. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()
|
|
30
|
+
* @deprecated Will fail on Android SDK >= 33. See https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#disable()
|
|
27
31
|
*/
|
|
28
32
|
disable(): Promise<void>;
|
|
29
33
|
/**
|
|
@@ -109,8 +113,9 @@ export interface BleClientInterface {
|
|
|
109
113
|
* Create a bond with a peripheral BLE device.
|
|
110
114
|
* Only available on **Android**. On iOS bonding is handled by the OS.
|
|
111
115
|
* @param deviceId The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan))
|
|
116
|
+
* @param options Options for plugin call
|
|
112
117
|
*/
|
|
113
|
-
createBond(deviceId: string): Promise<void>;
|
|
118
|
+
createBond(deviceId: string, options?: TimeoutOptions): Promise<void>;
|
|
114
119
|
/**
|
|
115
120
|
* Report whether a peripheral BLE device is bonded.
|
|
116
121
|
* Only available on **Android**. On iOS bonding is handled by the OS.
|
|
@@ -226,6 +231,7 @@ declare class BleClientClass implements BleClientInterface {
|
|
|
226
231
|
disableQueue(): void;
|
|
227
232
|
initialize(options?: InitializeOptions): Promise<void>;
|
|
228
233
|
isEnabled(): Promise<boolean>;
|
|
234
|
+
requestEnable(): Promise<void>;
|
|
229
235
|
enable(): Promise<void>;
|
|
230
236
|
disable(): Promise<void>;
|
|
231
237
|
startEnabledNotifications(callback: (value: boolean) => void): Promise<void>;
|
|
@@ -241,7 +247,7 @@ declare class BleClientClass implements BleClientInterface {
|
|
|
241
247
|
getDevices(deviceIds: string[]): Promise<BleDevice[]>;
|
|
242
248
|
getConnectedDevices(services: string[]): Promise<BleDevice[]>;
|
|
243
249
|
connect(deviceId: string, onDisconnect?: (deviceId: string) => void, options?: TimeoutOptions): Promise<void>;
|
|
244
|
-
createBond(deviceId: string): Promise<void>;
|
|
250
|
+
createBond(deviceId: string, options?: TimeoutOptions): Promise<void>;
|
|
245
251
|
isBonded(deviceId: string): Promise<boolean>;
|
|
246
252
|
disconnect(deviceId: string): Promise<void>;
|
|
247
253
|
getServices(deviceId: string): Promise<BleService[]>;
|
package/dist/esm/bleClient.js
CHANGED
|
@@ -27,6 +27,11 @@ class BleClientClass {
|
|
|
27
27
|
});
|
|
28
28
|
return enabled;
|
|
29
29
|
}
|
|
30
|
+
async requestEnable() {
|
|
31
|
+
await this.queue(async () => {
|
|
32
|
+
await BluetoothLe.requestEnable();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
30
35
|
async enable() {
|
|
31
36
|
await this.queue(async () => {
|
|
32
37
|
await BluetoothLe.enable();
|
|
@@ -148,9 +153,9 @@ class BleClientClass {
|
|
|
148
153
|
await BluetoothLe.connect(Object.assign({ deviceId }, options));
|
|
149
154
|
});
|
|
150
155
|
}
|
|
151
|
-
async createBond(deviceId) {
|
|
156
|
+
async createBond(deviceId, options) {
|
|
152
157
|
await this.queue(async () => {
|
|
153
|
-
await BluetoothLe.createBond({ deviceId });
|
|
158
|
+
await BluetoothLe.createBond(Object.assign({ deviceId }, options));
|
|
154
159
|
});
|
|
155
160
|
}
|
|
156
161
|
async isBonded(deviceId) {
|