universal_ble

Creator: coderz1093

Last updated:

Add to Cart

Description:

universal ble

UniversalBLE #

A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter.
Try it online, provided your browser supports Web Bluetooth.
Features #

Scanning
Connecting
Discovering Services
Reading & Writing data
Pairing
Bluetooth Availability
Command Queue
Timeout
UUID Format Agnostic

Usage #
API Support Matrix #



API
Android
iOS
macOS
Windows
Linux
Web




startScan/stopScan
✔️
✔️
✔️
✔️
✔️
✔️


connect/disconnect
✔️
✔️
✔️
✔️
✔️
✔️


getSystemDevices
✔️
✔️
✔️
✔️
✔️



discoverServices
✔️
✔️
✔️
✔️
✔️
✔️


readValue
✔️
✔️
✔️
✔️
✔️
✔️


writeValue
✔️
✔️
✔️
✔️
✔️
✔️


setNotifiable
✔️
✔️
✔️
✔️
✔️
✔️


pair
✔️
✔️
✔️
✔️
✔️



unpair
✔️


✔️
✔️



isPaired
✔️
✔️
✔️
✔️
✔️
✔️


onPairingStateChange
✔️


✔️
✔️



getBluetoothAvailabilityState
✔️
✔️
✔️
✔️
✔️



enableBluetooth
✔️


✔️
✔️



onAvailabilityChange
✔️
✔️
✔️
✔️
✔️
✔️


requestMtu
✔️
✔️
✔️
✔️
✔️




Getting Started #
Add universal_ble in your pubspec.yaml:
dependencies:
universal_ble:
copied to clipboard
and import it wherever you want to use it:
import 'package:universal_ble/universal_ble.dart';
copied to clipboard
Scanning #
// Set a scan result handler
UniversalBle.onScanResult = (bleDevice) {
// e.g. Use BleDevice ID to connect
}

// Perform a scan
UniversalBle.startScan();

// Or optionally add a scan filter
UniversalBle.startScan(
scanFilter: ScanFilter(
withServices: ["SERVICE_UUID"],
withManufacturerData: ["MANUFACTURER_DATA"]
)
);

// Stop scanning
UniversalBle.stopScan();
copied to clipboard
Before initiating a scan, ensure that Bluetooth is available:
AvailabilityState state = await UniversalBle.getBluetoothAvailabilityState();
// Start scan only if Bluetooth is powered on
if (state == AvailabilityState.poweredOn) {
UniversalBle.startScan();
}

// Or listen to bluetooth availability changes
UniversalBle.onAvailabilityChange = (state) {
if (state == AvailabilityState.poweredOn) {
UniversalBle.startScan();
}
};
copied to clipboard
See the Bluetooth Availability section for more.
System Devices
Already connected devices, connected either through previous sessions, other apps or through system settings, won't show up as scan results. You can get those using getSystemDevices().
// Get already connected devices
// You can set `withServices` to narrow down the results
// On `Apple`, `withServices` is required to get connected devices, else [1800] service will be used as default filter.
List<BleDevice> devices = await UniversalBle.getSystemDevices(withServices: []);
copied to clipboard
For each such device the isSystemDevice property will be true.
You still need to explicitly connect to them before being able to use them.
Scan Filter
You can optionally set filters when scanning.
With Services
When setting this parameter, the scan results will only include devices that advertise any of the specified services. This is the primary filter. All devices are first filtered by services, then further filtered by other criteria. This parameter is mandatory on web if you want to access those services.
List<String> withServices;
copied to clipboard
With ManufacturerData
Use the withManufacturerData parameter to filter devices by manufacturer data. When you pass a list of ManufacturerDataFilter objects to this parameter, the scan results will only include devices that contain any of the specified manufacturer data.
List<ManufacturerDataFilter> withManufacturerData;
copied to clipboard
With namePrefix
Use the withNamePrefix parameter to filter devices by names (case sensitive). When you pass a list of names, the scan results will only include devices that have this name or start with the provided parameter.
List<String> withNamePrefix;
copied to clipboard
Connecting #
// Connect to a device using the `deviceId` of the BleDevice received from `UniversalBle.onScanResult`
String deviceId = bleDevice.deviceId;
UniversalBle.connect(deviceId);

// Disconnect from a device
UniversalBle.disconnect(deviceId);

// Get connection/disconnection updates
UniversalBle.onConnectionChange = (String deviceId, bool isConnected) {
debugPrint('OnConnectionChange $deviceId, $isConnected');
}

// Get current connection state
// Can be connected, disconnected, connecting or disconnecting
BleConnectionState connectionState = await bleDevice.connectionState;
copied to clipboard
Discovering Services #
After establishing a connection, you need to discover services. This method will discover all services and their characteristics.
// Discover services of a specific device
UniversalBle.discoverServices(deviceId);
copied to clipboard
Reading & Writing data #
You need to first discover services before you are able to read and write to characteristics.
// Read data from a characteristic
UniversalBle.readValue(deviceId, serviceId, characteristicId);

// Write data to a characteristic
UniversalBle.writeValue(deviceId, serviceId, characteristicId, value);

// Subscribe to a characteristic
UniversalBle.setNotifiable(deviceId, serviceId, characteristicId, BleInputProperty.notification);

// Get characteristic updates in `onValueChange`
UniversalBle.onValueChange = (String deviceId, String characteristicId, Uint8List value) {
debugPrint('onValueChange $deviceId, $characteristicId, ${hex.encode(value)}');
}

// Unsubscribe from a characteristic
UniversalBle.setNotifiable(deviceId, serviceId, characteristicId, BleInputProperty.disabled);
copied to clipboard
Pairing #
// Pair
bool? isPaired = await UniversalBle.pair(deviceId); // Returns true if successful

// For Apple and Web, you can optionally pass a pairingCommand if you know an encrypted read or write characteristic.
// Not supported on Web/Windows
UniversalBle.pair(deviceId, pairingCommand: BleCommand(service:"SERVICE", characteristic:"ENCRYPTED_CHARACTERISTIC",));

// Receive pairing state changes
UniversalBle.onPairingStateChange = (String deviceId, bool isPaired) {
// Handle pairing state change
}

// Unpair
UniversalBle.unpair(deviceId);

// Check current pairing state
bool? isPaired = UniversalBle.isPaired(deviceId);
copied to clipboard
Bluetooth Availability #
// Get current Bluetooth availability state
AvailabilityState availabilityState = UniversalBle.getBluetoothAvailabilityState(); // e.g. poweredOff or poweredOn,

// Receive Bluetooth availability changes
UniversalBle.onAvailabilityChange = (state) {
// Handle the new Bluetooth availability state
};

// Enable Bluetooth programmatically
UniversalBle.enableBluetooth();
copied to clipboard
Command Queue #
By default, all commands are executed in a global queue (QueueType.global), with each command waiting for the previous one to finish.
If you want to parallelize commands between multiple devices, you can set:
// Create a separate queue for each device.
UniversalBle.queueType = QueueType.perDevice;
copied to clipboard
You can also disable the queue completely and parallelize all commands, even for the same device, by using:
// Disable queue
UniversalBle.queueType = QueueType.none;
copied to clipboard
Keep in mind that some platforms (e.g. Android) may not handle well devices that fail to process consecutive commands without a minimum interval. Therefore, it is not advised to set queueType to none.
You can get queue updates by setting:
// Get queue state updates
UniversalBle.onQueueUpdate = (String id, int remainingItems) {
debugPrint("Queue: $id Remaining: $remainingItems");
};
copied to clipboard
Timeout #
By default, all commands have a timeout of 10 seconds.
// Change timeout
UniversalBle.timeout = const Duration(seconds: 10);

// Disable timeout
UniversalBle.timeout = null;
copied to clipboard
UUID Format Agnostic #
UniversalBLE is agnostic to the UUID format of services and characteristics regardless of the platform the app runs on. When passing a UUID, you can pass it in any format (long/short) or character case (upper/lower case) you want. UniversalBLE will take care of necessary conversions, across all platforms, so that you don't need to worry about underlying platform differences.
For consistency, all characteristic and service UUIDs will be returned in lowercase 128-bit format, across all platforms, e.g. 0000180a-0000-1000-8000-00805f9b34fb.
Utility Methods #
If you need to convert any UUIDs in your app you can use the following methods.

BleUuidParser.string() converts a string to a 128-bit UUID formatted string:

BleUuidParser.string("180A"); // "0000180a-0000-1000-8000-00805f9b34fb"

BleUuidParser.string("0000180A-0000-1000-8000-00805F9B34FB"); // "0000180a-0000-1000-8000-00805f9b34fb"
copied to clipboard

BleUuidParser.number() converts a number to a 128-bit UUID formatted string:

BleUuidParser.number(0x180A); // "0000180a-0000-1000-8000-00805f9b34fb"
copied to clipboard

BleUuidParser.compare() compares two differently formatted UUIDs:

BleUuidParser.compare("180a","0000180A-0000-1000-8000-00805F9B34FB"); // true
copied to clipboard
Platform-specific Setup #
Android #
Add the following permissions to your AndroidManifest.xml file:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
copied to clipboard
If you use BLUETOOTH_SCAN to determine location, modify your AndroidManifest.xml file to include the following entry:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" tools:remove="android:usesPermissionFlags" tools:targetApi="s" />
copied to clipboard
If your app uses location services, remove android:maxSdkVersion="30" from the location permission tags.
iOS / macOS #
Add NSBluetoothPeripheralUsageDescription and NSBluetoothAlwaysUsageDescription to Info.plist of your iOS and macOS app.
Add the Bluetooth capability to the macOS app from Xcode.
Windows / Linux #
Your Bluetooth adapter needs to support at least Bluetooth 4.0. If you have more than 1 adapters, the first one returned from the system will be picked.
When publishing on Windows you need to declare the following capabilities: bluetooth, radios.
Web #
On web, the withServices parameter in the ScanFilter is used as optional_services as well as a services filter. On web you have to set this parameter to ensure that you can access the specified services after connecting to the device. You can leave it empty for the rest of the platforms if your device does not advertise services.
ScanFilter(
withServices: kIsWeb ? ["SERVICE_UUID"] : [],
)
copied to clipboard
Customizing Platform Implementation of UniversalBle #
// Create a class that extends UniversalBlePlatform
class UniversalBleMock extends UniversalBlePlatform {
// Implement all commands
}

UniversalBle.setInstance(UniversalBleMock());
copied to clipboard

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.