WebF native plugin for Bluetooth Low Energy (BLE) operations. This plugin wraps the flutter_blue_plus Flutter package to provide BLE device scanning, connection management, service discovery, and GATT operations for WebF applications.
- Scan for nearby BLE devices with optional filters
- Connect and disconnect from BLE devices
- Discover services and characteristics
- Read and write characteristic values
- Subscribe to characteristic notifications
- Monitor connection state changes
- Request MTU size (Android)
Add the dependency to your Flutter app's pubspec.yaml:
dependencies:
webf: ^0.24.0
webf_bluetooth: ^1.0.0Register the module in your main.dart:
import 'package:webf/webf.dart';
import 'package:webf_bluetooth/webf_bluetooth.dart';
void main() {
WebFControllerManager.instance.initialize(WebFControllerManagerConfig(
maxAliveInstances: 2,
maxAttachedInstances: 1,
));
// Register Bluetooth module
WebF.defineModule((context) => BluetoothModule(context));
runApp(MyApp());
}Install the npm package:
npm install @openwebf/webf-bluetoothimport { WebFBluetooth } from '@openwebf/webf-bluetooth';
// Listen for scan results (module events)
const unsubscribeScan = WebFBluetooth.addListener('scanResult', (_event, device) => {
console.log(`Found: ${device.name || 'Unknown'} (${device.deviceId})`);
console.log(`RSSI: ${device.rssi} dBm`);
});
// Start scanning
const result = await WebFBluetooth.startScan({
timeout: 10000, // 10 seconds
serviceUuids: ['180D'], // Filter by Heart Rate service
});
if (result.success === 'true') {
console.log('Scanning started');
}
// Stop scanning when done
await WebFBluetooth.stopScan();
// Stop listening
unsubscribeScan();// Connect to a device
const connectResult = await WebFBluetooth.connect({
deviceId: 'AA:BB:CC:DD:EE:FF',
timeout: 15000,
autoConnect: false,
});
if (connectResult.success === 'true') {
console.log('Connected! MTU:', connectResult.mtu);
}
// Listen for connection state changes
WebFBluetooth.addListener('connectionState', (_event, detail) => {
console.log(`Device ${detail.deviceId}: ${detail.state}`);
});const servicesResult = await WebFBluetooth.discoverServices('AA:BB:CC:DD:EE:FF');
if (servicesResult.success === 'true') {
const services = JSON.parse(servicesResult.services!);
services.forEach(service => {
console.log(`Service: ${service.uuid}`);
service.characteristics.forEach(char => {
console.log(` Characteristic: ${char.uuid}`);
console.log(` Properties:`, char.properties);
});
});
}// Read a characteristic
const readResult = await WebFBluetooth.readCharacteristic({
deviceId: 'AA:BB:CC:DD:EE:FF',
serviceUuid: '180D',
characteristicUuid: '2A37',
});
if (readResult.success === 'true') {
console.log('Value (hex):', readResult.value);
console.log('Value (base64):', readResult.valueBase64);
}
// Write to a characteristic
const writeResult = await WebFBluetooth.writeCharacteristic({
deviceId: 'AA:BB:CC:DD:EE:FF',
serviceUuid: 'custom-service-uuid',
characteristicUuid: 'custom-char-uuid',
value: '0102030405', // hex string
withoutResponse: false,
});// Listen for notifications
WebFBluetooth.addListener('notification', (_event, detail) => {
const { characteristicUuid, value, valueBase64 } = detail;
console.log(`Notification from ${characteristicUuid}: ${value}`);
});
// Subscribe to Heart Rate Measurement
const subResult = await WebFBluetooth.subscribeToNotifications({
deviceId: 'AA:BB:CC:DD:EE:FF',
serviceUuid: '180D',
characteristicUuid: '2A37',
});
if (subResult.success === 'true') {
console.log('Subscribed! ID:', subResult.subscriptionId);
}
// Unsubscribe when done
await WebFBluetooth.unsubscribeFromNotifications(subResult.subscriptionId);// Check if Bluetooth is on
const stateResult = await WebFBluetooth.getAdapterState();
console.log('Adapter state:', stateResult.state);
// Check if scanning
const scanningResult = await WebFBluetooth.isScanning();
console.log('Is scanning:', scanningResult.isScanning);
// Get connected devices
const devicesResult = await WebFBluetooth.getConnectedDevices();
const devices = JSON.parse(devicesResult.devices!);
console.log('Connected devices:', devices);If you don't want to use WebFBluetooth.addListener(...), you can listen to module events directly:
webf.addWebfModuleListener('Bluetooth', (event, extra) => {
if (event.type === 'scanResult') {
console.log('scanResult', extra);
}
});| Method | Description |
|---|---|
getAdapterState() |
Get current Bluetooth adapter state |
isBluetoothOn() |
Check if Bluetooth is enabled |
turnOn() |
Turn on Bluetooth (Android only) |
| Method | Description |
|---|---|
startScan(options?) |
Start scanning for BLE devices |
stopScan() |
Stop active scan |
isScanning() |
Check if currently scanning |
| Method | Description |
|---|---|
connect(options) |
Connect to a BLE device |
disconnect(deviceId) |
Disconnect from a device |
getConnectionState(deviceId) |
Get connection state |
getConnectedDevices() |
List connected devices |
requestMtu(deviceId, mtu) |
Request MTU size (Android) |
| Method | Description |
|---|---|
discoverServices(deviceId) |
Discover services and characteristics |
| Method | Description |
|---|---|
readCharacteristic(options) |
Read characteristic value |
writeCharacteristic(options) |
Write to characteristic |
readDescriptor(options) |
Read descriptor value |
writeDescriptor(options) |
Write to descriptor |
| Method | Description |
|---|---|
subscribeToNotifications(options) |
Subscribe to characteristic notifications |
unsubscribeFromNotifications(subscriptionId) |
Unsubscribe from notifications |
| Event | Description |
|---|---|
scanResult |
Emitted for each device found during scanning |
connectionState |
Emitted when connection state changes |
notification |
Emitted when a subscribed characteristic value changes |
| Platform | Support |
|---|---|
| Android | Yes |
| iOS | Yes |
| macOS | Yes |
| Linux | Yes (via BlueZ) |
Add to AndroidManifest.xml:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />Add to Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to connect to BLE devices.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses Bluetooth to connect to BLE devices.</string>- BLE Central Role only: This plugin supports scanning and connecting to peripherals. It does not support acting as a BLE peripheral.
- No Bluetooth Classic: Devices using Bluetooth Classic (HC-05, speakers, headphones, mice, keyboards) are not supported.
- No iBeacon on iOS: iBeacons require CoreLocation on iOS.
MIT License - see the LICENSE file for details.
- flutter_blue_plus - The underlying BLE plugin
- WebF Documentation
- WebF Native Plugins