@capacitor-community/bluetooth-le
Capacitor plugin for Bluetooth Low Energy
Maintainer | GitHub |
---|---|
Patrick Wespi | pwespi |
Philip Peitsch | peitschie |
Plugin | Capacitor | Documentation |
---|---|---|
6.x | 6.x | README |
3.x | 5.x | README |
2.x | 4.x | README |
1.x | 3.x | README |
0.x | 2.x | README |
This is a Capacitor plugin for Bluetooth Low Energy. It supports the web, Android and iOS.
The goal is to support the same features on all platforms. Therefore the Web Bluetooth API is taken as a guidline for what features to implement.
This plugin only supports Bluetooth Low Energy, not Bluetooth serial / classic.
Furthermore the plugin only supports the central role of the Bluetooth Low Energy protocol. If you need the peripheral role, take a look a these plugins:
For support of Web Bluetooth in various browsers, see implementation status.
Below is an index of all the methods available.
See Platform Support for an overview of supported methods on Android, iOS and web.
npm install @capacitor-community/bluetooth-le
npx cap sync
On iOS, add the NSBluetoothAlwaysUsageDescription
to Info.plist
, otherwise the app will crash when trying to use Bluetooth (see here).
If the app needs to use Bluetooth while it is in the background, you also have to add bluetooth-central
to UIBackgroundModes
(for details see here).
./ios/App/App/Info.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
...
+ <key>NSBluetoothAlwaysUsageDescription</key>
+ <string>Uses Bluetooth to connect and interact with peripheral BLE devices.</string>
+ <key>UIBackgroundModes</key>
+ <array>
+ <string>bluetooth-central</string>
+ </array>
</dict>
</plist>
Note: Bluetooth is not available in the iOS simulator. The initialize
call will be rejected with an error "BLE unsupported". You have to test your app on a real device.
On Android, no further steps are required to use the plugin.
If your app targets Android 12 (API level 31) or higher and your app doesn't use Bluetooth scan results to derive physical location information, you can strongly assert that your app doesn't derive physical location. This allows the app to scan for Bluetooth devices without asking for location permissions. See the Android documentation.
The following steps are required to scan for Bluetooth devices without location permission on Android 12 devices:
android/variables.gradle
, make sure compileSdkVersion
and targetSdkVersion
are at least 31 (changing those values can have other consequences on your app, so make sure you know what you're doing).android/app/src/main/AndroidManifest.xml
, update the permissions:
<!-- Permissions -->
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
+ android:usesPermissionFlags="neverForLocation"
+ tools:targetApi="s" />
androidNeverForLocation
flag to true
when initializing the BleClient
.
import { BleClient } from '@capacitor-community/bluetooth-le';
await BleClient.initialize({ androidNeverForLocation: true });
You can configure the strings that are displayed in the device selection dialog on iOS and Android when using requestDevice()
:
./capacitor.config.json
:
{
"...": "other configuration",
"plugins": {
"BluetoothLe": {
"displayStrings": {
"scanning": "Am Scannen...",
"cancel": "Abbrechen",
"availableDevices": "Verfügbare Geräte",
"noDeviceFound": "Kein Gerät gefunden"
}
}
}
}
The default values are:
{
"plugins": {
"BluetoothLe": {
"displayStrings": {
"scanning": "Scanning...",
"cancel": "Cancel",
"availableDevices": "Available devices",
"noDeviceFound": "No device found"
}
}
}
}
The display strings can also be set at run-time using setDisplayStrings(...)
.
There is a plugin wrapper class BleClient
which makes events and method arguments easier to work with.
// Import the wrapper class
import { BleClient } from '@capacitor-community/bluetooth-le';
Note: It is not recommended to use the BluetoothLe
plugin class directly.
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.
import { BleClient, numbersToDataView, numberToUUID } from '@capacitor-community/bluetooth-le';
const HEART_RATE_SERVICE = '0000180d-0000-1000-8000-00805f9b34fb';
const HEART_RATE_MEASUREMENT_CHARACTERISTIC = '00002a37-0000-1000-8000-00805f9b34fb';
const BODY_SENSOR_LOCATION_CHARACTERISTIC = '00002a38-0000-1000-8000-00805f9b34fb';
const BATTERY_SERVICE = numberToUUID(0x180f);
const BATTERY_CHARACTERISTIC = numberToUUID(0x2a19);
const POLAR_PMD_SERVICE = 'fb005c80-02e7-f387-1cad-8acd2d8df0c8';
const POLAR_PMD_CONTROL_POINT = 'fb005c81-02e7-f387-1cad-8acd2d8df0c8';
export async function main(): Promise<void> {
try {
await BleClient.initialize();
const device = await BleClient.requestDevice({
services: [HEART_RATE_SERVICE],
optionalServices: [BATTERY_SERVICE, POLAR_PMD_SERVICE],
});
// connect to device, the onDisconnect callback is optional
await BleClient.connect(device.deviceId, (deviceId) => onDisconnect(deviceId));
console.log('connected to device', device);
const result = await BleClient.read(device.deviceId, HEART_RATE_SERVICE, BODY_SENSOR_LOCATION_CHARACTERISTIC);
console.log('body sensor location', result.getUint8(0));
const battery = await BleClient.read(device.deviceId, BATTERY_SERVICE, BATTERY_CHARACTERISTIC);
console.log('battery level', battery.getUint8(0));
await BleClient.write(device.deviceId, POLAR_PMD_SERVICE, POLAR_PMD_CONTROL_POINT, numbersToDataView([1, 0]));
console.log('written [1, 0] to control point');
await BleClient.startNotifications(
device.deviceId,
HEART_RATE_SERVICE,
HEART_RATE_MEASUREMENT_CHARACTERISTIC,
(value) => {
console.log('current heart rate', parseHeartRate(value));
}
);
// disconnect after 10 sec
setTimeout(async () => {
await BleClient.stopNotifications(device.deviceId, HEART_RATE_SERVICE, HEART_RATE_MEASUREMENT_CHARACTERISTIC);
await BleClient.disconnect(device.deviceId);
console.log('disconnected from device', device);
}, 10000);
} catch (error) {
console.error(error);
}
}
function onDisconnect(deviceId: string): void {
console.log(`device ${deviceId} disconnected`);
}
function parseHeartRate(value: DataView): number {
const flags = value.getUint8(0);
const rate16Bits = flags & 0x1;
let heartRate: number;
if (rate16Bits > 0) {
heartRate = value.getUint16(1, true);
} else {
heartRate = value.getUint8(1);
}
return heartRate;
}
Here is an example of using the scanning API.
import { BleClient, numberToUUID } from '@capacitor-community/bluetooth-le';
const HEART_RATE_SERVICE = numberToUUID(0x180d);
export async function scan(): Promise<void> {
try {
await BleClient.initialize();
await BleClient.requestLEScan(
{
services: [HEART_RATE_SERVICE],
},
(result) => {
console.log('received new scan result', result);
}
);
setTimeout(async () => {
await BleClient.stopLEScan();
console.log('stopped scanning');
}, 5000);
} catch (error) {
console.error(error);
}
}
Note: web support depends on the browser, see implementation status.
method | Android | iOS | web |
---|---|---|---|
initialize() |
✅ | ✅ | ✅ |
isEnabled() |
✅ | ✅ | -- |
requestEnable() |
✅ | ❌ | ❌ |
enable() |
✅ | ❌ | ❌ |
disable() |
✅ | ❌ | ❌ |
startEnabledNotifications(...) |
✅ | ✅ | -- |
stopEnabledNotifications() |
✅ | ✅ | -- |
isLocationEnabled() |
✅ | ❌ | ❌ |
openLocationSettings() |
✅ | ❌ | ❌ |
openBluetoothSettings() |
✅ | ❌ | ❌ |
openAppSettings() |
✅ | ✅ | ❌ |
setDisplayStrings(...) |
✅ | ✅ | -- |
requestDevice(...) |
✅ | ✅ | ✅ |
requestLEScan(...) |
✅ | ✅ | 🚩 |
stopLEScan() |
✅ | ✅ | 🚩 |
getDevices(...) |
✅ | ✅ | 🚩 |
getConnectedDevices(...) |
✅ | ✅ | 🚩 |
connect(...) |
✅ | ✅ | ✅ |
createBond(...) |
✅ | ❌ | ❌ |
isBonded(...) |
✅ | ❌ | ❌ |
disconnect(...) |
✅ | ✅ | ✅ |
getServices(...) |
✅ | ✅ | ✅ |
discoverServices(...) |
✅ | ✅ | ❌ |
getMtu(...) |
✅ | ✅ | ❌ |
requestConnectionPriority(...) |
✅ | ❌ | ❌ |
readRssi(...) |
✅ | ✅ | ❌ |
read(...) |
✅ | ✅ | ✅ |
write(...) |
✅ | ✅ | ✅ |
readDescriptor(...) |
✅ | ✅ | ✅ |
writeDescriptor(...) |
✅ | ✅ | ✅ |
writeWithoutResponse(...) |
✅ | ✅ | ✅ |
startNotifications(...) |
✅ | ✅ | ✅ |
stopNotifications(...) |
✅ | ✅ | ✅ |
unavailable
error)InitializeOptions
|
---
### isEnabled()
```typescript
isEnabled() => PromisePromise<boolean>
---
### requestEnable()
```typescript
requestEnable() => Promise(value: boolean) => void
| Callback function to use when the Bluetooth state changes. |
---
### stopEnabledNotifications()
```typescript
stopEnabledNotifications() => PromisePromise<boolean>
---
### openLocationSettings()
```typescript
openLocationSettings() => PromiseDisplayStrings
|
---
### requestDevice(...)
```typescript
requestDevice(options?: RequestBleDeviceOptions | undefined) => PromiseRequestBleDeviceOptions
| Device filters, see [RequestBleDeviceOptions](#RequestBleDeviceOptions) |
**Returns:** Promise<BleDevice>
---
### requestLEScan(...)
```typescript
requestLEScan(options: RequestBleDeviceOptions, callback: (result: ScanResult) => void) => PromiseRequestBleDeviceOptions
|
| **`callback`** | (result: ScanResult) => void
|
---
### stopLEScan()
```typescript
stopLEScan() => Promisestring[]
| List of device IDs, e.g. saved from a previous app run. |
**Returns:** Promise<BleDevice[]>
---
### getConnectedDevices(...)
```typescript
getConnectedDevices(services: string[]) => Promisestring[]
| List of services to filter the devices by. If no service is specified, no devices will be returned. Only applies to iOS. |
**Returns:** Promise<BleDevice[]>
---
### connect(...)
```typescript
connect(deviceId: string, onDisconnect?: ((deviceId: string) => void) | undefined, options?: TimeoutOptions | undefined) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`onDisconnect`** | ((deviceId: string) => void)
| Optional disconnect callback function that will be used when the device disconnects |
| **`options`** | TimeoutOptions
| Options for plugin call |
---
### createBond(...)
```typescript
createBond(deviceId: string, options?: TimeoutOptions | undefined) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`options`** | TimeoutOptions
| Options for plugin call |
---
### isBonded(...)
```typescript
isBonded(deviceId: string) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
**Returns:** Promise<boolean>
---
### disconnect(...)
```typescript
disconnect(deviceId: string) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
---
### getServices(...)
```typescript
getServices(deviceId: string) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
**Returns:** Promise<BleService[]>
---
### discoverServices(...)
```typescript
discoverServices(deviceId: string) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
---
### getMtu(...)
```typescript
getMtu(deviceId: string) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
**Returns:** Promise<number>
---
### requestConnectionPriority(...)
```typescript
requestConnectionPriority(deviceId: string, connectionPriority: ConnectionPriority) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`connectionPriority`** | ConnectionPriority
| Request a specific connection priority. See [ConnectionPriority](#connectionpriority) |
---
### readRssi(...)
```typescript
readRssi(deviceId: string) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
**Returns:** Promise<number>
---
### read(...)
```typescript
read(deviceId: string, service: string, characteristic: string, options?: TimeoutOptions | undefined) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`service`** | string
| UUID of the service (see [UUID format](#uuid-format)) |
| **`characteristic`** | string
| UUID of the characteristic (see [UUID format](#uuid-format)) |
| **`options`** | TimeoutOptions
| Options for plugin call |
**Returns:** Promise<DataView>
---
### write(...)
```typescript
write(deviceId: string, service: string, characteristic: string, value: DataView, options?: TimeoutOptions | undefined) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`service`** | string
| UUID of the service (see [UUID format](#uuid-format)) |
| **`characteristic`** | string
| UUID of the characteristic (see [UUID format](#uuid-format)) |
| **`value`** | DataView
| The value to write as a DataView. To create a DataView from an array of numbers, there is a helper function, e.g. numbersToDataView([1, 0]) |
| **`options`** | TimeoutOptions
| Options for plugin call |
---
### writeWithoutResponse(...)
```typescript
writeWithoutResponse(deviceId: string, service: string, characteristic: string, value: DataView, options?: TimeoutOptions | undefined) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`service`** | string
| UUID of the service (see [UUID format](#uuid-format)) |
| **`characteristic`** | string
| UUID of the characteristic (see [UUID format](#uuid-format)) |
| **`value`** | DataView
| The value to write as a DataView. To create a DataView from an array of numbers, there is a helper function, e.g. numbersToDataView([1, 0]) |
| **`options`** | TimeoutOptions
| Options for plugin call |
---
### readDescriptor(...)
```typescript
readDescriptor(deviceId: string, service: string, characteristic: string, descriptor: string, options?: TimeoutOptions | undefined) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`service`** | string
| UUID of the service (see [UUID format](#uuid-format)) |
| **`characteristic`** | string
| UUID of the characteristic (see [UUID format](#uuid-format)) |
| **`descriptor`** | string
| UUID of the descriptor (see [UUID format](#uuid-format)) |
| **`options`** | TimeoutOptions
| Options for plugin call |
**Returns:** Promise<DataView>
---
### writeDescriptor(...)
```typescript
writeDescriptor(deviceId: string, service: string, characteristic: string, descriptor: string, value: DataView, options?: TimeoutOptions | undefined) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`service`** | string
| UUID of the service (see [UUID format](#uuid-format)) |
| **`characteristic`** | string
| UUID of the characteristic (see [UUID format](#uuid-format)) |
| **`descriptor`** | string
| UUID of the descriptor (see [UUID format](#uuid-format)) |
| **`value`** | DataView
| The value to write as a DataView. To create a DataView from an array of numbers, there is a helper function, e.g. numbersToDataView([1, 0]) |
| **`options`** | TimeoutOptions
| Options for plugin call |
---
### startNotifications(...)
```typescript
startNotifications(deviceId: string, service: string, characteristic: string, callback: (value: DataView) => void) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`service`** | string
| UUID of the service (see [UUID format](#uuid-format)) |
| **`characteristic`** | string
| UUID of the characteristic (see [UUID format](#uuid-format)) |
| **`callback`** | (value: DataView) => void
| Callback function to use when the value of the characteristic changes |
---
### stopNotifications(...)
```typescript
stopNotifications(deviceId: string, service: string, characteristic: string) => Promisestring
| The ID of the device to use (obtained from [requestDevice](#requestDevice) or [requestLEScan](#requestLEScan)) |
| **`service`** | string
| UUID of the service (see [UUID format](#uuid-format)) |
| **`characteristic`** | string
| UUID of the characteristic (see [UUID format](#uuid-format)) |
---
### Interfaces
#### InitializeOptions
| Prop | Type | Description | Default |
| ----------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ |
| **`androidNeverForLocation`** | boolean
| If your app doesn't use Bluetooth scan results to derive physical location information, you can strongly assert that your app doesn't derive physical location. (Android only) Requires adding 'neverForLocation' to AndroidManifest.xml https://developer.android.com/guide/topics/connectivity/bluetooth/permissions#assert-never-for-location | false
|
#### DisplayStrings
| Prop | Type | Default | Since |
| ---------------------- | ------------------- | -------------------------------- | ----- |
| **`scanning`** | string
| "Scanning..."
| 0.0.1 |
| **`cancel`** | string
| "Cancel"
| 0.0.1 |
| **`availableDevices`** | string
| "Available devices"
| 0.0.1 |
| **`noDeviceFound`** | string
| "No device found"
| 0.0.1 |
#### BleDevice
| Prop | Type | Description |
| -------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`deviceId`** | string
| ID of the device, which will be needed for further calls. On **Android** this is the BLE MAC address. On **iOS** and **web** it is an identifier. |
| **`name`** | string
| Name of the peripheral device. |
| **`uuids`** | string[]
| |
#### RequestBleDeviceOptions
| Prop | Type | Description |
| ---------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`services`** | string[]
| Filter devices by service UUIDs. UUIDs have to be specified as 128 bit UUID strings, e.g. ['0000180d-0000-1000-8000-00805f9b34fb'] There is a helper function to convert numbers to UUIDs. e.g. [numberToUUID(0x180f)]. (see [UUID format](#uuid-format)) |
| **`name`** | string
| Filter devices by name |
| **`namePrefix`** | string
| Filter devices by name prefix |
| **`optionalServices`** | string[]
| For **web**, all services that will be used have to be listed under services or optionalServices, e.g. [numberToUUID(0x180f)] (see [UUID format](#uuid-format)) |
| **`allowDuplicates`** | boolean
| Normally scans will discard the second and subsequent advertisements from a single device. If you need to receive them, set allowDuplicates to true (only applicable in `requestLEScan`). (default: false) |
| **`scanMode`** | ScanMode
| Android scan mode (default: ScanMode.SCAN_MODE_BALANCED) |
#### ScanResult
| Prop | Type | Description |
| ---------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`device`** | BleDevice
| The peripheral device that was found in the scan. **Android** and **web**: `device.name` is always identical to `localName`. **iOS**: `device.name` is identical to `localName` the first time a device is discovered, but after connecting `device.name` is the cached GAP name in subsequent scans. |
| **`localName`** | string
| The name of the peripheral device from the advertisement data. |
| **`rssi`** | number
| Received Signal Strength Indication. |
| **`txPower`** | number
| Transmit power in dBm. A value of 127 indicates that it is not available. |
| **`manufacturerData`** | { [key: string]: DataView; }
| Manufacturer data, key is a company identifier and value is the data. |
| **`serviceData`** | { [key: string]: DataView; }
| Service data, key is a service UUID and value is the data. |
| **`uuids`** | string[]
| Advertised services. |
| **`rawAdvertisement`** | DataView
| Raw advertisement data (**Android** only). |
#### DataView
| Prop | Type |
| ---------------- | --------------------------------------------------- |
| **`buffer`** | ArrayBuffer
|
| **`byteLength`** | number
|
| **`byteOffset`** | number
|
| Method | Signature | Description |
| -------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **getFloat32** | (byteOffset: number, littleEndian?: boolean \| undefined) => number | Gets the Float32 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **getFloat64** | (byteOffset: number, littleEndian?: boolean \| undefined) => number | Gets the Float64 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **getInt8** | (byteOffset: number) => number | Gets the Int8 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **getInt16** | (byteOffset: number, littleEndian?: boolean \| undefined) => number | Gets the Int16 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **getInt32** | (byteOffset: number, littleEndian?: boolean \| undefined) => number | Gets the Int32 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **getUint8** | (byteOffset: number) => number | Gets the Uint8 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **getUint16** | (byteOffset: number, littleEndian?: boolean \| undefined) => number | Gets the Uint16 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **getUint32** | (byteOffset: number, littleEndian?: boolean \| undefined) => number | Gets the Uint32 value at the specified byte offset from the start of the view. There is no alignment constraint; multi-byte values may be fetched from any offset. |
| **setFloat32** | (byteOffset: number, value: number, littleEndian?: boolean \| undefined) => void | Stores an Float32 value at the specified byte offset from the start of the view. |
| **setFloat64** | (byteOffset: number, value: number, littleEndian?: boolean \| undefined) => void | Stores an Float64 value at the specified byte offset from the start of the view. |
| **setInt8** | (byteOffset: number, value: number) => void | Stores an Int8 value at the specified byte offset from the start of the view. |
| **setInt16** | (byteOffset: number, value: number, littleEndian?: boolean \| undefined) => void | Stores an Int16 value at the specified byte offset from the start of the view. |
| **setInt32** | (byteOffset: number, value: number, littleEndian?: boolean \| undefined) => void | Stores an Int32 value at the specified byte offset from the start of the view. |
| **setUint8** | (byteOffset: number, value: number) => void | Stores an Uint8 value at the specified byte offset from the start of the view. |
| **setUint16** | (byteOffset: number, value: number, littleEndian?: boolean \| undefined) => void | Stores an Uint16 value at the specified byte offset from the start of the view. |
| **setUint32** | (byteOffset: number, value: number, littleEndian?: boolean \| undefined) => void | Stores an Uint32 value at the specified byte offset from the start of the view. |
#### ArrayBuffer
Represents a raw buffer of binary data, which is used to store data for the
different typed arrays. ArrayBuffers cannot be read from or written to directly,
but can be passed to a typed array or DataView Object to interpret the raw
buffer as needed.
| Prop | Type | Description |
| ---------------- | ------------------- | ------------------------------------------------------------------------------- |
| **`byteLength`** | number
| Read-only. The length of the ArrayBuffer (in bytes). |
| Method | Signature | Description |
| --------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| **slice** | (begin: number, end?: number \| undefined) => ArrayBuffer | Returns a section of an ArrayBuffer. |
#### TimeoutOptions
| Prop | Type | Description |
| ------------- | ------------------- | ---------------------------------------------------------------------------------------------------------- |
| **`timeout`** | number
| Timeout in milliseconds for plugin call. Default is 10000 for `connect` and 5000 for other plugin methods. |
#### BleService
| Prop | Type |
| --------------------- | -------------------------------- |
| **`uuid`** | string
|
| **`characteristics`** | BleCharacteristic[]
|
#### BleCharacteristic
| Prop | Type |
| ----------------- | ----------------------------------------------------------------------------------- |
| **`uuid`** | string
|
| **`properties`** | BleCharacteristicProperties
|
| **`descriptors`** | BleDescriptor[]
|
#### BleCharacteristicProperties
| Prop | Type |
| -------------------------------- | -------------------- |
| **`broadcast`** | boolean
|
| **`read`** | boolean
|
| **`writeWithoutResponse`** | boolean
|
| **`write`** | boolean
|
| **`notify`** | boolean
|
| **`indicate`** | boolean
|
| **`authenticatedSignedWrites`** | boolean
|
| **`reliableWrite`** | boolean
|
| **`writableAuxiliaries`** | boolean
|
| **`extendedProperties`** | boolean
|
| **`notifyEncryptionRequired`** | boolean
|
| **`indicateEncryptionRequired`** | boolean
|
#### BleDescriptor
| Prop | Type |
| ---------- | ------------------- |
| **`uuid`** | string
|
### Enums
#### ScanMode
| Members | Value | Description |
| --------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`SCAN_MODE_LOW_POWER`** | 0
| Perform Bluetooth LE scan in low power mode. This mode is enforced if the scanning application is not in foreground. https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_LOW_POWER |
| **`SCAN_MODE_BALANCED`** | 1
| Perform Bluetooth LE scan in balanced power mode. (default) Scan results are returned at a rate that provides a good trade-off between scan frequency and power consumption. https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_BALANCED |
| **`SCAN_MODE_LOW_LATENCY`** | 2
| Scan using highest duty cycle. It's recommended to only use this mode when the application is running in the foreground. https://developer.android.com/reference/android/bluetooth/le/ScanSettings#SCAN_MODE_LOW_LATENCY |
#### ConnectionPriority
| Members | Value | Description |
| ----------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`CONNECTION_PRIORITY_BALANCED`** | 0
| Use the connection parameters recommended by the Bluetooth SIG. This is the default value if no connection parameter update is requested. https://developer.android.com/reference/android/bluetooth/BluetoothGatt#CONNECTION_PRIORITY_BALANCED |
| **`CONNECTION_PRIORITY_HIGH`** | 1
| Request a high priority, low latency connection. An application should only request high priority connection parameters to transfer large amounts of data over LE quickly. Once the transfer is complete, the application should request CONNECTION_PRIORITY_BALANCED connection parameters to reduce energy use. https://developer.android.com/reference/android/bluetooth/BluetoothGatt#CONNECTION_PRIORITY_HIGH |
| **`CONNECTION_PRIORITY_LOW_POWER`** | 2
| Request low power, reduced data rate connection parameters. https://developer.android.com/reference/android/bluetooth/BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER |
All UUIDs have to be provided in 128 bit format as string, e.g. '0000180d-0000-1000-8000-00805f9b34fb'
. There is a helper function to convert 16 bit UUID numbers to string:
import { numberToUUID } from '@capacitor-community/bluetooth-le';
const HEART_RATE_SERVICE = numberToUUID(0x180d);
// '0000180d-0000-1000-8000-00805f9b34fb'
On some Android devices connect()
may fail when the device was connected before, even if the device is not actually connected.
In that case you should first call disconnect()
, e.g.:
const device = await BleClient.requestDevice({
// ...
});
// ...
await BleClient.disconnect(device.deviceId);
await BleClient.connect(device.deviceId);
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.
async function initialize() {
// Check if location is enabled
if (this.platform.is('android')) {
const isLocationEnabled = await BleClient.isLocationEnabled();
if (!isLocationEnabled) {
await BleClient.openLocationSettings();
}
}
await BleClient.initialize();
}
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!