universal_bluetooth 0.0.2
universal_bluetooth: ^0.0.2 copied to clipboard
A universal Bluetooth plugin for Flutter supporting Classic Bluetooth, BLE, and iBeacon.
Universal Bluetooth Plugin for Flutter #
A comprehensive Flutter plugin that provides unified access to Classic Bluetooth, Bluetooth Low Energy (BLE), and iBeacon functionality across iOS and Android platforms.
corp : https://jamkrafters.com
🚀 Features #
✅ Classic Bluetooth #
- Device scanning and discovery
- Connection management (pairing/disconnection)
- Bidirectional data communication
- Connection state monitoring
- Make device discoverable to other devices
✅ BLE (Bluetooth Low Energy) #
- BLE device scanning with service filtering
- GATT connection management
- Service and characteristic discovery
- Read/Write characteristic values
- Characteristic notifications and subscriptions
- Connection state monitoring
✅ iBeacon Support #
- iBeacon advertising (iOS/Android)
- iBeacon scanning and ranging
- Proximity detection
- Region monitoring
📦 Installation #
Add this to your package's pubspec.yaml file:
dependencies:
universal_bluetooth: ^0.0.1
🔧 Setup #
Android Setup #
Add the following permissions to your android/app/src/main/AndroidManifest.xml:
<!-- Basic Bluetooth permissions -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- For Android 12+ (API 31+) -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Location permissions for BLE and Beacon scanning -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
iOS Setup #
Add the following to your ios/Runner/Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs access to Bluetooth to communicate with devices</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs access to Bluetooth to communicate with devices</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs location access for beacon functionality</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access for beacon functionality</string>
📱 Usage #
1️⃣ Basic Setup and Status Check #
import 'package:universal_bluetooth/universal_bluetooth.dart';
// Check if Bluetooth is available and enabled
final isAvailable = await UniversalBluetooth.isBluetoothAvailable;
final isEnabled = await UniversalBluetooth.isBluetoothEnabled;
// Request to enable Bluetooth
if (!isEnabled) {
final enabled = await UniversalBluetooth.requestBluetoothEnable();
}
// Get my Bluetooth address
final address = await UniversalBluetooth.getBluetoothAddress();
2️⃣ Classic Bluetooth Usage #
Device Scanning
// Start scanning for devices
await UniversalBluetooth.startBluetoothScan();
// Listen for discovered devices
UniversalBluetooth.bluetoothScanResults.listen((result) {
print('Found device: ${result.device.name} (${result.device.address})');
print('Signal strength: ${result.device.rssi}dBm');
});
// Listen for scan completion
UniversalBluetooth.bluetoothScanFinished.listen((_) {
print('Scan completed');
});
// Stop scanning
await UniversalBluetooth.stopBluetoothScan();
Make Device Discoverable
// Make device discoverable for 300 seconds
final success = await UniversalBluetooth.startBluetoothDiscoverable(
duration: 300
);
// Stop discoverable mode
await UniversalBluetooth.stopBluetoothDiscoverable();
Connection and Data Communication
// Connect to a device
await UniversalBluetooth.connectToBluetoothDevice(deviceId);
// Monitor connection state
UniversalBluetooth.bluetoothConnectionStateChanged(deviceId).listen((state) {
switch (state) {
case BluetoothConnectionState.connected:
print('Connected');
break;
case BluetoothConnectionState.disconnected:
print('Disconnected');
break;
case BluetoothConnectionState.connecting:
print('Connecting...');
break;
case BluetoothConnectionState.error:
print('Connection error');
break;
}
});
// Send data
final message = "Hello, Bluetooth!";
await UniversalBluetooth.sendBluetoothData(
deviceId,
message.codeUnits
);
// Receive data
UniversalBluetooth.bluetoothDataReceived(deviceId).listen((data) {
final receivedMessage = String.fromCharCodes(data);
print('Received message: $receivedMessage');
});
// Disconnect
await UniversalBluetooth.disconnectBluetoothDevice(deviceId);
3️⃣ BLE (Bluetooth Low Energy) Usage #
BLE Scanning
// Start BLE scanning (scan for specific services)
await UniversalBluetooth.startBleScan(
serviceUuids: ['180F'], // Battery Service UUID (optional)
timeout: Duration(seconds: 30),
);
// Listen for discovered BLE devices
UniversalBluetooth.bleScanResults.listen((device) {
print('Found BLE device: ${device.name} (RSSI: ${device.rssi})');
});
// Stop BLE scanning
await UniversalBluetooth.stopBleScan();
BLE Connection and GATT Operations
// Connect to BLE device
await UniversalBluetooth.connectToBleDevice(deviceId);
// Discover services
final services = await UniversalBluetooth.discoverBleServices(deviceId);
// Get characteristics for a service
final characteristics = await UniversalBluetooth.getBleCharacteristics(
deviceId,
serviceUuid,
);
// Read characteristic value
final data = await UniversalBluetooth.readBleCharacteristic(
deviceId,
serviceUuid,
characteristicUuid,
);
// Write to characteristic
await UniversalBluetooth.writeBleCharacteristic(
deviceId,
serviceUuid,
characteristicUuid,
[0x01, 0x02, 0x03],
);
// Subscribe to characteristic notifications
await UniversalBluetooth.subscribeBleCharacteristic(
deviceId,
serviceUuid,
characteristicUuid,
);
// Listen for characteristic value changes
UniversalBluetooth.bleCharacteristicValueChanged(
deviceId,
serviceUuid,
characteristicUuid,
).listen((data) {
print('Characteristic value changed: $data');
});
// Disconnect BLE device
await UniversalBluetooth.disconnectBleDevice(deviceId);
4️⃣ iBeacon Usage #
iBeacon Advertising
// Request location permission (required for beacon functionality)
final hasPermission = await UniversalBluetooth.requestLocationPermission();
// Start advertising as iBeacon
await UniversalBluetooth.startBeaconAdvertising(
uuid: 'E2C56DB5-DFFB-48D2-B060-D0F5A71096E0',
major: 1,
minor: 100,
identifier: 'MyBeacon',
);
// Stop beacon advertising
await UniversalBluetooth.stopBeaconAdvertising();
iBeacon Scanning
// Start scanning for beacons
await UniversalBluetooth.startBeaconScanning(
uuids: ['E2C56DB5-DFFB-48D2-B060-D0F5A71096E0'],
);
// Listen for discovered beacons
UniversalBluetooth.beaconScanResults.listen((beacon) {
print('Found beacon: ${beacon.uuid}');
print('Major: ${beacon.major}, Minor: ${beacon.minor}');
print('Distance: ${beacon.distance}m');
print('Proximity: ${beacon.proximity}');
});
// Stop beacon scanning
await UniversalBluetooth.stopBeaconScanning();
📊 Data Models #
BluetoothDevice #
class BluetoothDevice {
final String id; // Device ID
final String name; // Device name
final String address; // MAC address
final bool isConnected; // Connection status
final int? rssi; // Signal strength
final List<String> serviceUuids; // Service UUID list
}
BleDevice #
class BleDevice {
final String id; // Device ID
final String name; // Device name
final String address; // MAC address
final int rssi; // Signal strength
final List<String> serviceUuids; // Service UUID list
final bool isConnectable; // Whether device is connectable
}
BeaconDevice #
class BeaconDevice {
final String uuid; // Beacon UUID
final int major; // Major value
final int minor; // Minor value
final int rssi; // Signal strength
final double? distance; // Estimated distance (meters)
final BeaconProximity proximity; // Proximity
}
enum BeaconProximity { immediate, near, far, unknown }
BluetoothConnectionState #
enum BluetoothConnectionState {
disconnected, // Disconnected
connecting, // Connecting
connected, // Connected
disconnecting, // Disconnecting
error, // Error
}
🔍 Debug and Extension Functions #
// Get list of connected devices
final connectedDevices = await UniversalBluetoothExtensions.getConnectedDevices();
// Send test data
final result = await UniversalBluetoothExtensions.testDataSend(deviceId);
// Set global method call handler
UniversalBluetoothExtensions.setMethodCallHandler((call) async {
// Handle custom method calls
});
🎯 Platform Support #
| Feature | Android | iOS |
|---|---|---|
| Classic Bluetooth | ✅ | ✅ |
| BLE | ✅ | ✅ |
| iBeacon Advertising | ✅ | ✅ |
| iBeacon Scanning | ✅ | ✅ |
📋 Requirements #
- Flutter: 3.3.0+
- Dart: 3.8.1+
- Android: API level 21+ (Android 5.0+)
- iOS: 11.0+
⚠️ Important Notes #
- Permissions: Android 12+ requires new Bluetooth permissions
- Location Permission: Required for BLE scanning and iBeacon functionality
- Background Operation: Additional setup may be required for background operation
- iOS Limitations: iOS doesn't provide access to actual Bluetooth MAC addresses for privacy reasons
📝 Complete Example #
import 'package:flutter/material.dart';
import 'package:universal_bluetooth/universal_bluetooth.dart';
class BluetoothExample extends StatefulWidget {
@override
_BluetoothExampleState createState() => _BluetoothExampleState();
}
class _BluetoothExampleState extends State<BluetoothExample> {
List<BluetoothScanResult> devices = [];
bool isScanning = false;
@override
void initState() {
super.initState();
_initBluetooth();
}
Future<void> _initBluetooth() async {
// Check and request Bluetooth enable
final isEnabled = await UniversalBluetooth.isBluetoothEnabled;
if (!isEnabled) {
await UniversalBluetooth.requestBluetoothEnable();
}
// Listen for scan results
UniversalBluetooth.bluetoothScanResults.listen((result) {
setState(() {
final index = devices.indexWhere(
(device) => device.device.address == result.device.address,
);
if (index >= 0) {
devices[index] = result;
} else {
devices.add(result);
}
});
});
}
Future<void> _startScan() async {
setState(() {
devices.clear();
isScanning = true;
});
await UniversalBluetooth.startBluetoothScan();
}
Future<void> _stopScan() async {
await UniversalBluetooth.stopBluetoothScan();
setState(() {
isScanning = false;
});
}
Future<void> _connectDevice(String deviceId) async {
try {
await UniversalBluetooth.connectToBluetoothDevice(deviceId);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Connecting to device...')),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Connection failed: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Universal Bluetooth Example'),
actions: [
IconButton(
icon: Icon(isScanning ? Icons.stop : Icons.search),
onPressed: isScanning ? _stopScan : _startScan,
),
],
),
body: ListView.builder(
itemCount: devices.length,
itemBuilder: (context, index) {
final result = devices[index];
final device = result.device;
return ListTile(
title: Text(device.name.isNotEmpty ? device.name : 'Unknown Device'),
subtitle: Text('${device.address}\nRSSI: ${device.rssi}dBm'),
trailing: ElevatedButton(
onPressed: () => _connectDevice(device.id),
child: Text('Connect'),
),
leading: Icon(Icons.bluetooth),
);
},
),
);
}
}
📖 API Reference #
Core Methods #
| Method | Description |
|---|---|
isBluetoothAvailable |
Check if Bluetooth is available on device |
isBluetoothEnabled |
Check if Bluetooth is currently enabled |
requestBluetoothEnable() |
Request user to enable Bluetooth |
getBluetoothAddress() |
Get device Bluetooth address |
Classic Bluetooth #
| Method | Description |
|---|---|
startBluetoothScan() |
Start scanning for Classic Bluetooth devices |
stopBluetoothScan() |
Stop Classic Bluetooth scanning |
startBluetoothDiscoverable({duration}) |
Make device discoverable |
stopBluetoothDiscoverable() |
Stop discoverable mode |
connectToBluetoothDevice(deviceId) |
Connect to a Classic Bluetooth device |
disconnectBluetoothDevice(deviceId) |
Disconnect from a Classic Bluetooth device |
sendBluetoothData(deviceId, data) |
Send data to connected Classic Bluetooth device |
Bluetooth Low Energy #
| Method | Description |
|---|---|
startBleScan({serviceUuids, timeout}) |
Start BLE scanning with optional filters |
stopBleScan() |
Stop BLE scanning |
connectToBleDevice(deviceId) |
Connect to a BLE device |
disconnectBleDevice(deviceId) |
Disconnect from a BLE device |
discoverBleServices(deviceId) |
Discover services on connected BLE device |
getBleCharacteristics(deviceId, serviceUuid) |
Get characteristics for a service |
readBleCharacteristic(deviceId, serviceUuid, characteristicUuid) |
Read characteristic value |
writeBleCharacteristic(deviceId, serviceUuid, characteristicUuid, data) |
Write to characteristic |
subscribeBleCharacteristic(deviceId, serviceUuid, characteristicUuid) |
Subscribe to characteristic notifications |
unsubscribeBleCharacteristic(deviceId, serviceUuid, characteristicUuid) |
Unsubscribe from characteristic notifications |
iBeacon #
| Method | Description |
|---|---|
isBeaconSupported |
Check if iBeacon is supported |
startBeaconAdvertising({uuid, major, minor, identifier}) |
Start advertising as iBeacon |
stopBeaconAdvertising() |
Stop beacon advertising |
startBeaconScanning({uuids}) |
Start scanning for beacons |
stopBeaconScanning() |
Stop beacon scanning |
requestLocationPermission() |
Request location permission for beacon functionality |
🔗 Additional Resources #
For complete examples and advanced usage, check the /example folder which includes:
- Classic Bluetooth scanning and connection
- Bidirectional data communication
- BLE device connection and GATT operations
- iBeacon advertising and scanning
- Permission management
- Error handling
🤝 Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License #
This project is licensed under the MIT License - see the LICENSE file for details.
🆘 Support #
If you encounter any issues or have questions, please file an issue on the GitHub repository.
Universal Bluetooth Plugin makes it easy to integrate all Bluetooth functionality into your Flutter applications, from simple device connections to complex IoT applications.