Capacitor Community Bluetooth Low Energy

repository·main·Indexed 18 days ago

https://github.com/capacitor-community/bluetooth-le

A Capacitor plugin providing Bluetooth Low Energy (BLE) capabilities for Web, Android, and iOS, modeled after the Web Bluetooth API. It supports the Central role and provides the BleClient wrapper class for managing device initialization, scanning, connecting, and data exchange via read, write, and notifications. Note: It does not support Bluetooth Classic or Serial.

Tokens
21.4K
Snippets
67
Records
78
Agent score
59%

What's inside @capacitor-community/bluetooth-le

  1. Overview of Bluetooth Low Energy plugin capabilities

    main

    This plugin provides Bluetooth Low Energy (BLE) support for Web, Android, and iOS. It follows the Web Bluetooth API as a guideline for feature parity across platforms.

    Key Constraints:

    • Supports Bluetooth Low Energy (BLE) only. It does not support Bluetooth Classic or Serial.
    • Supports the Central role only. If you need to implement the Peripheral role, use alternative plugins like cordova-plugin-bluetoothle or cordova-plugin-ble-peripheral.

    Core API Methods:

    • initialize(...): Prepares the plugin for use.
    • requestDevice(...): Triggers a device selection dialog.
    • connect(...) / disconnect(...): Manages connections to peripherals.
    • read(...) / write(...): Handles data exchange with characteristics.
    • startNotifications(...) / stopNotifications(...): Manages characteristic notifications.
  2. Use the BleClient wrapper class

    main

    Instead of using the BluetoothLe plugin class directly, it is highly recommended to use the BleClient wrapper class. BleClient provides a more developer-friendly API by making events and method arguments easier to work with.

    import { BleClient } from '@capacitor-community/bluetooth-le';
    // Import the wrapper class
    import { BleClient } from '@capacitor-community/bluetooth-le';
  3. Configure Android 12+ Bluetooth permissions (Optional)

    main

    If your app targets Android 12 (API level 31) or higher and does not use Bluetooth scan results to derive physical location, you can scan for devices without requesting location permissions by following these steps:

    1. Ensure compileSdkVersion and targetSdkVersion are at least 31 in android/variables.gradle.
    2. Update android/app/src/main/AndroidManifest.xml to include the following 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" />
    1. Set the androidNeverForLocation flag to true when calling BleClient.initialize().

    Warning: Using neverForLocation may cause some BLE beacons to be filtered out of scan results.

    import { BleClient } from '@capacitor-community/bluetooth-le';
    await BleClient.initialize({ androidNeverForLocation: true });
  4. Configure iOS permissions for Bluetooth

    main

    On iOS, you must add usage descriptions to your Info.plist to prevent the app from crashing when accessing Bluetooth. If your app requires Bluetooth functionality in the background, you must also declare the bluetooth-central background mode.

    Note: Bluetooth is not available in the iOS simulator. The initialize call will fail with an error BLE unsupported. Testing must be done on a real device.

    <?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>
  5. Use the Bluetooth LE plugin

    main

    The @capacitor-community/bluetooth-le plugin provides a unified API for interacting with Bluetooth Low Energy devices on iOS, Android, and Web. To use the plugin, import the core functionality from the package. The main entry point exports all necessary definitions, the BLE client implementation, conversion utilities, and configuration options.

    import { BleClient } from '@capacitor-community/bluetooth-le';
    
    // The plugin is typically used via the BleClient class
  6. Configure Android location permission assertion

    main

    When initializing the plugin on Android, if your application does not use Bluetooth scan results to derive physical location information, you can set androidNeverForLocation to true.

    Note: This requires adding neverForLocation to your AndroidManifest.xml to comply with Android's permission model.

    // Example initialization option
    await BleClient.initialize({
      androidNeverForLocation: true
    });
  7. Understand ScanResult data

    main

    A ScanResult contains detailed information about a device found during a scan.

    • device: The BleDevice object.
    • localName: The name from the advertisement data.
    • rssi: Received Signal Strength Indication.
    • txPower: Transmit power in dBm (127 if unavailable).
    • manufacturerData: A map where keys are company identifiers and values are DataView objects.
    • serviceData: A map where keys are service UUIDs and values are DataView objects.
    • uuids: Advertised service UUIDs.
    • rawAdvertisement: (Android only) The raw DataView of the advertisement.
  8. Configure Bluetooth device selection display strings

    main

    You can customize the text shown in the device selection dialog on iOS and Android (used during requestDevice()) via capacitor.config.json or at runtime using setDisplayStrings(...).

    Available keys in the displayStrings object:

    • scanning: Text shown while scanning.
    • cancel: Text for the cancel button.
    • availableDevices: Header text for the list of devices.
    • noDeviceFound: Text shown when no devices are detected.
    {
      "plugins": {
        "BluetoothLe": {
          "displayStrings": {
            "scanning": "Am Scannen...",
            "cancel": "Abbrechen",
            "availableDevices": "Verfügbare Geräte",
            "noDeviceFound": "Kein Gerät gefunden"
          }
        }
      }
    }
  9. Perform Read and Write operations

    main

    To interact with characteristics or descriptors, use the read and write methods.

    Note on Data Types:

    • For write and writeDescriptor, the value type depends on the platform:
      • Android/iOS: string
      • Web: DataView
    • For read and readDescriptor, the returned value follows the same platform pattern.

    Common Options: Both operations accept TimeoutOptions to specify a timeout in milliseconds (defaults to 5000ms for these methods).

    // Example Write
    await BluetoothLePlugin.write({
      deviceId: 'MY_DEVICE_ID',
      service: '0000180d-0000-1000-8000-00805f9b34fb',
      characteristic: '00002a37-0000-1000-8000-00805f9b34fb',
      value: 'some_value_or_data_view',
      timeout: 2000
    });
  10. Fix 'No devices found' on Android by enabling location services

    main

    On Android, BleClient.initialize() requests location permissions. However, if location services are disabled at the OS level, the app will not find any devices. You should check if location is enabled using BleClient.isLocationEnabled() and, if not, prompt the user to enable it using BleClient.openLocationSettings().

    async function initialize() {
      // Check if location is enabled
      if (Capacitor.getPlatform() === 'android') {
        const isLocationEnabled = await BleClient.isLocationEnabled();
        if (!isLocationEnabled) {
          await BleClient.openLocationSettings();
        }
      }
      await BleClient.initialize();
    }
  11. Fix connection failures on Android

    main

    On some Android devices, BleClient.connect() may fail if the device was previously connected, even if it is not currently active. To resolve this, explicitly call BleClient.disconnect() using the deviceId before attempting to connect.

    const device = await BleClient.requestDevice({
       // ...
    });
    // ...
    await BleClient.disconnect(device.deviceId);
    await BleClient.connect(device.deviceId);