# flutter_blue_plus
**Repository Path**: etlevent/flutter_blue_plus
## Basic Information
- **Project Name**: flutter_blue_plus
- **Description**: flutter_blue_plus fork
- **Primary Language**: Unknown
- **License**: BSD-3-Clause
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-05-10
- **Last Updated**: 2024-04-26
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[](https://pub.dartlang.org/packages/flutter_blue_plus)
**Note: this plugin is continuous work from FlutterBlue since maintenance stopped.**
## Contents
- [Introduction](#introduction)
- [Usage](#usage)
- [Getting Started](#getting-started)
- [Reference](#reference)
- [Debugging](#debugging)
- [Common Problems](#common-problems)
## Introduction
FlutterBluePlus is a Bluetooth Low Energy plugin for [Flutter](https://flutter.dev).
It supports BLE Central Role only (most common).
If you need BLE Peripheral Role, you should check out [FlutterBlePeripheral](https://pub.dev/packages/flutter_ble_peripheral).
## ❗ Bluetooth Classic is not supported ❗
i.e. speakers, headphones, mice, keyboards, gamepads, Arduino HC-05 & HC-06, and more are not supported. These all use Bluetooth Classic.
Also, iBeacons are **_not_** supported on iOS. Apple requires you to use CoreLocation.
## Cross-Platform Bluetooth Low Energy
FlutterBluePlus aims to offer the most from all supported platforms: iOS, macOS, Android.
The code is written to be simple, robust, and incredibly easy to understand.
## No Dependencies
FlutterBluePlus has zero dependencies besides Flutter, Android, and iOS themselves.
This makes FlutterBluePlus very stable, and easy to maintain.
## ⭐ Stars ⭐
Please star this repo & on [pub.dev](https://pub.dev/packages/flutter_blue_plus). We all benefit from having a larger community.
## Usage
### Error Handling :fire:
Flutter Blue Plus takes error handling very seriously.
Every error returned by the native platform is checked and thrown as an exception where appropriate. See [Reference](#reference) for a list of throwable functions.
**Streams:** At the time of writing, streams returned by Flutter Blue Plus never emit any errors and never close. There's no need to handle `onError` or `onDone` for `stream.listen(...)`.
---
### Set Log Level
```dart
// if your terminal doesn't support color you'll see annoying logs like `\x1B[1;35m`
FlutterBluePlus.setLogLevel(LogLevel.verbose, color:false)
```
Setting `LogLevel.verbose` shows *all* data in and out.
⚫ = function name
🟣 = args to platform
🟡 = data from platform
### Enable Bluetooth
**Note:** On iOS, a "*This app would like to use Bluetooth*" system dialogue appears on first call to a FlutterBluePlus method. This is when the `CBCentralManager` (iOS) & `BluetoothManager` (Android) are initialized.
```dart
// check adapter availability
if (await FlutterBluePlus.isAvailable == false) {
print("Bluetooth not supported by this device");
return;
}
// turn on bluetooth ourself if we can
// for iOS, the user controls bluetooth enable/disable
if (Platform.isAndroid) {
await FlutterBluePlus.turnOn();
}
// wait bluetooth to be on & print states
// note: for iOS the initial state is typically BluetoothAdapterState.unknown
// note: if you have permissions issues you will get stuck at BluetoothAdapterState.unauthorized
await FlutterBluePlus.adapterState
.map((s){print(s);return s;})
.where((s) => s == BluetoothAdapterState.on)
.first;
```
### Scan for devices
If your device is not found, see [Common Problems](#common-problems).
```dart
// Setup Listener for scan results
// device not found? see "Common Problems" in the README
var subscription = FlutterBluePlus.scanResults.listen((results) {
for (ScanResult r in results) {
print('${r.device.localName} found! rssi: ${r.rssi}');
}
});
// Start scanning
FlutterBluePlus.startScan(timeout: Duration(seconds: 4));
// Stop scanning
await FlutterBluePlus.stopScan();
```
### Connect to a device
```dart
// listen for disconnection
device.connectionState.listen((BluetoothConnectionState state) async {
if (state == BluetoothConnectionState.disconnected) {
// typically, start a periodic timer that tries to periodically reconnect.
// Note: you must always re-discover services after disconnection!
}
});
// Connect to the device
await device.connect();
// Disconnect from device
await device.disconnect();
```
### Discover services
```dart
// Note: You must call this again if disconnected!
List services = await device.discoverServices();
services.forEach((service) {
// do something with service
});
```
### Read and write characteristics
```dart
// Reads all characteristics
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
List value = await c.read();
print(value);
}
// Writes to a characteristic
await c.write([0x12, 0x34])
```
If you want write large messages regardless of mtu, define this function.
```dart
import 'dart:math';
// split large writes
// Note: This can only be used for write (with response) to avoid data loss
extension WriteLarge on BluetoothCharacteristic {
Future writeLarge(List value, int mtu, {int timeout = 15}) async {
int chunk = mtu-3;
for (int i = 0; i < value.length; i += chunk) {
List subvalue = value.sublist(i, min(i + chunk, value.length));
await write(subvalue, withoutResponse:false, timeout: timeout);
}
}
}
```
### Read and write descriptors
```dart
// Reads all descriptors
var descriptors = characteristic.descriptors;
for(BluetoothDescriptor d in descriptors) {
List value = await d.read();
print(value);
}
// Writes to a descriptor
await d.write([0x12, 0x34])
```
### Set notifications and listen to changes
If onValueReceived is never called, see [Common Problems](#common-problems) in the README.
```dart
// Setup Listener for characteristic reads
// If this is never called, see "Common Problems" in the README
characteristic.onValueReceived.listen((value) {
// do something with new value
});
// enable notifications
await characteristic.setNotifyValue(true);
```
### Get Connected System Devices
These devices are already connected to the system, but must be reconnected by *your app* before you can communicate with them.
```dart
List connectedSystemDevices = await FlutterBluePlus.connectedSystemDevices;
for (var d in connectedSystemDevices) {
await d.connect(); // Must connect *our* app to the device
await d.discoverServices();
}
```
### Read the MTU and request larger size
```dart
final mtu = await device.mtu.first;
await device.requestMtu(512);
```
Note that iOS will not allow requests of MTU size, and will always try to negotiate the highest possible MTU (iOS supports up to MTU size 185)
## Getting Started
### Change the minSdkVersion for Android
flutter_blue_plus is compatible only from version 21 of Android SDK so you should change this in **android/app/build.gradle**:
```dart
Android {
defaultConfig {
minSdkVersion: 21
```
### Add permissions for Android (No Location)
In the **android/app/src/main/AndroidManifest.xml** add:
```xml
```
### Add permissions for Android (With Fine Location)
If you want to use Bluetooth to determine location.
In the **android/app/src/main/AndroidManifest.xml** add:
```xml
```
And set androidUsesFineLocation when scanning:
```dart
// Start scanning
flutterBlue.startScan(timeout: Duration(seconds: 4), androidUsesFineLocation: true);
```
### Android Proguard
Add the following line in your `project/android/app/proguard-rules.pro` file:
```
-keep class com.boskokg.flutter_blue_plus.* { *; }
```
to avoid seeing the following kind errors in your `release` builds:
```
PlatformException(startScan, Field androidScanMode_ for m0.e0 not found. Known fields are
[private int m0.e0.q, private b3.b0$i m0.e0.r, private boolean m0.e0.s, private static final m0.e0 m0.e0.t,
private static volatile b3.a1 m0.e0.u], java.lang.RuntimeException: Field androidScanMode_ for m0.e0 not found
```
### Add permissions for iOS
In the **ios/Runner/Info.plist** let’s add:
```dart
NSBluetoothAlwaysUsageDescription
Need BLE permission
NSBluetoothPeripheralUsageDescription
Need BLE permission
NSLocationAlwaysAndWhenInUseUsageDescription
Need Location permission
NSLocationAlwaysUsageDescription
Need Location permission
NSLocationWhenInUseUsageDescription
Need Location permission
```
For location permissions on iOS see more at: [https://developer.apple.com/documentation/corelocation/requesting_authorization_for_location_services](https://developer.apple.com/documentation/corelocation/requesting_authorization_for_location_services)
## Reference
### FlutterBlue API
| | Android | iOS | Throws | Description |
| :--------------------- | :----------------: | :----------------: | :----: | :----------------------------------------------------------|
| isAvailable | :white_check_mark: | :white_check_mark: | | Checks whether the device supports Bluetooth |
| turnOn | :white_check_mark: | | :fire: | Turns on the bluetooth adapter |
| adapterState | :white_check_mark: | :white_check_mark: | | Stream of on & off states of the bluetooth adapter |
| scan | :white_check_mark: | :white_check_mark: | :fire: | Starts a scan for Ble devices and returns a stream |
| startScan | :white_check_mark: | :white_check_mark: | :fire: | Starts a scan for Ble devices with no return value |
| stopScan | :white_check_mark: | :white_check_mark: | :fire: | Stop an existing scan for Ble devices |
| scanResults | :white_check_mark: | :white_check_mark: | | Stream of live scan results |
| isScanning | :white_check_mark: | :white_check_mark: | | Stream of current scanning state |
| isScanningNow | :white_check_mark: | :white_check_mark: | | Is a scan currently running? |
| connectedSystemDevices | :white_check_mark: | :white_check_mark: | | List of already connected devices, including by other apps |
| setLogLevel | :white_check_mark: | :white_check_mark: | | Configure plugin log level |
### BluetoothDevice API
| | Android | iOS | Throws | Description |
| :------------------------ | :----------------: | :----------------: | :----: | :----------------------------------------------------------|
| localName | :white_check_mark: | :white_check_mark: | | The cached localName of the device |
| connect | :white_check_mark: | :white_check_mark: | :fire: | Establishes a connection to the device |
| disconnect | :white_check_mark: | :white_check_mark: | :fire: | Cancels an active or pending connection to the device |
| discoverServices | :white_check_mark: | :white_check_mark: | :fire: | Discover services |
| isDiscoveryingServices | :white_check_mark: | :white_check_mark: | | Stream of whether service discovery is in progress |
| servicesList | :white_check_mark: | :white_check_mark: | | The list of services that were discovered |
| servicesStream | :white_check_mark: | :white_check_mark: | | Stream of services changes |
| connectionState | :white_check_mark: | :white_check_mark: | | Stream of connection changes for the Bluetooth Device |
| bondState | :white_check_mark: | | | Stream of device bond state. Can be useful on Android |
| mtu | :white_check_mark: | :white_check_mark: | :fire: | Stream of mtu size changes |
| readRssi | :white_check_mark: | :white_check_mark: | :fire: | Read RSSI from a connected device |
| requestMtu | :white_check_mark: | | :fire: | Request to change the MTU for the device |
| requestConnectionPriority | :white_check_mark: | | :fire: | Request to update a high priority, low latency connection |
| createBond | :white_check_mark: | | :fire: | Force a system pairing dialogue to show, if needed |
| removeBond | :white_check_mark: | | :fire: | Remove Bluetooth Bond of device |
| setPreferredPhy | :white_check_mark: | | | Set preferred RX and TX phy for connection and phy options |
| clearGattCache | :white_check_mark: | | :fire: | Clear android cache of service discovery results |
### BluetoothCharacteristic API
| | Android | iOS | Throws | Description |
| :------------- | :----------------: | :----------------: | :----: | :--------------------------------------------------------------|
| uuid | :white_check_mark: | :white_check_mark: | | The uuid of characeristic |
| read | :white_check_mark: | :white_check_mark: | :fire: | Retrieves the value of the characteristic |
| write | :white_check_mark: | :white_check_mark: | :fire: | Writes the value of the characteristic |
| setNotifyValue | :white_check_mark: | :white_check_mark: | :fire: | Sets notifications or indications on the characteristic |
| isNotifying | :white_check_mark: | :white_check_mark: | | Are notifications or indications currently enabled |
| onValueReceived | :white_check_mark: | :white_check_mark: | | Stream of characteristic value updates received from the device|
| lastValue | :white_check_mark: | :white_check_mark: | | The most recent value of the characteristic |
| lastValueStream | :white_check_mark: | :white_check_mark: | | Stream of lastValue + onValueReceived |
### BluetoothDescriptor API
| | Android | iOS | Throws | Description |
| :---- | :----------------: | :----------------: | :----: | :----------------------------------------------|
| uuid | :white_check_mark: | :white_check_mark: | | The uuid of descriptor |
| read | :white_check_mark: | :white_check_mark: | :fire: | Retrieves the value of the descriptor |
| write | :white_check_mark: | :white_check_mark: | :fire: | Writes the value of the descriptor |
| onValueReceived | :white_check_mark: | :white_check_mark: | | Stream of descriptor value reads & writes |
| lastValue | :white_check_mark: | :white_check_mark: | | The most recent value of the descriptor |
| lastValueStream | :white_check_mark: | :white_check_mark: | | Stream of lastValue + onValueReceived |
## Debugging
The easiest way to debug issues in FlutterBluePlus is to make your own local copy.
```
cd /user/downloads
git clone https://github.com/boskokg/flutter_blue_plus.git
```
then in `pubspec.yaml` add the repo by path:
```
flutter_blue_plus:
path: /user/downloads/flutter_blue_plus
```
Now you can edit the FlutterBluePlus code yourself.
## Common Problems
Many common problems are easily solved.
---
### Scanning does not find my device
**1. your device uses bluetooth classic, not BLE.**
Headphones, speakers, keyboards, mice, gamepads, & printers all use Bluetooth Classic.
These devices may be found in System Settings, but they cannot be connected to by FlutterBluePlus. FlutterBluePlus only supports Bluetooth Low Energy.
**2. your device stopped advertising.**
- you might need to reboot your device
- you might need put your device in "discovery mode"
- your phone may have already connected automatically
- another app may have already connected to your device
- another phone may have already connected to your device
Try looking through already connected devices:
```dart
// search already connected devices, including devices
// connected to by other apps
List system = await FlutterBluePlus.connectedSystemDevices;
for (var d in system) {
print('${r.device.localName} already connected to! ${r.device.remoteId}');
if (d.localName == "myBleDevice") {
await r.connect(); // must connect our app
}
}
```
**3. your scan filters are wrong.**
- try removing all scan filters
- for `withServices` to work, your device must actively advertise the serviceUUIDs it supports
**4. try a ble scanner app**
Search the App Store for a BLE scanner apps.
You should check if they can discover your device.
---
### Connection fails
**1. Your ble device may be low battery**
Bluetooth can become erratic when your peripheral device is low battery.
**2. Your ble device may have refused the connection or have a bug**
Connection is a two-way process. Your ble device may be misconfigured.
**3. You may be on the edge of the Bluetooth range.**
The signal is too weak, or there are a lot of devices causing radio interference.
**4. Some phones have an issue connecting while scanning.**
The Huawei P8 Lite is one of the reported phones to have this issue. Try stopping your scanner before connecting.
**5. Try restarting your phone**
Bluetooth is a complicated system service, and can enter a bad state.
---
### onValueReceived is never called
**1. you are not subscribed OR not calling read**
Your device will only send values after you call `await characteristic.setNotifyValue(true)`, or `await characteristic.read()`
**2. you are calling write**
`onValueReceived` is only called for reads & notifies.
You can do a single read with `await characteristic.read(...)`
**3. your device has nothing to send**
If you are using `setNotifyValue`, your device chooses when to send data.
Try interacting with your device to get it to send new data.
**4. your device has bugs**
Try rebooting your ble device.
Some ble devices have buggy software and stop sending data.
---
### characteristic writes fails
**1. the characeristic is not writeable**
Not all characeristics support `write`.
Your device must have configured this characteristic to support `write`.
**2. the data length is too long**
Characteristics only support writes up to a certain size.
`writeWithoutResponse`: you can only write up to (MTU-3) at a time. This is a BLE limitation.
`write`: look in the [Usage](#usage) section for a `writeLarge` function you can use to solve this issue.
**3. the characeristic does not support writeWithoutResponse**
Not all characeristics support `writeWithoutResponse`.
Your device must have configured this characteristic to support `writeWithoutResponse`.
**4. your bluetooth device turned off, or is out of range**
If your device turns off mid-write, it will cause a failure.
**5. your bluetooth device has bugs**
Maybe your device crashed, or is not sending a response due to software bugs.
**6. there is radio interference**
Bluetooth is wireless and will not always work.
---
### characteristic read fails
**1. the characeristic is not readable**
Not all characeristics support `read`.
Your device must have configured this characteristic to support `read`.
**2. your bluetooth device turned off, or is out of range**
If your device turns off mid-read, it will cause a failure.
**3. your bluetooth device has bugs**
Maybe your device crashed, or is not sending a response due to software bugs.
**4. there is radio interference**
Bluetooth is wireless and will not always work.