flutter_ble_lib 2.2.3

  • Readme
  • Changelog
  • Example
  • Installing
  • 94

Frontside Build Status pub package

Flutter BLE library logo

FlutterBleLib #

A library for all your Bluetooth Low Energy needs in Flutter. Internally utilises Polidea's MultiPlatformBleAdapter, which runs on RxAndroidBle and RxBluetoothKit.

BLE Simulator #

This library supports BLEmulator, the BLE simulator. The simulation allows one to develop without physical smartphone or BLE peripheral and use one's production BLE–related code in automated testing.

Installation #

To use this plugin, add flutter_ble_lib as a dependency in your pubspec.yaml file.

Android #

Set minSDKVersion in [project]/android/app/build.gradle file to 18.

defaultConfig {
  ...
  minSdkVersion 18
  ...
}

Support for Bluetooth Low Energy has been added in API 18, hence the library requires minSDKVersion to be set to 18. If BLE is not core to your application, you can override it and handle support detection in your code.

Notice: You don't need to add any permissions related to BLE to the AndroidManifest.xml, because they are already declared in the library's native module. However, you still need to request ACCESS_FINE_LOCATION permission at runtime to be able to scan for peripheral. See example's code and example's pubspec.

iOS #

Go to [project]/ios directory and run pod install.

Add Privacy - Bluetooth Always Usage Description key to [project]/ios/Runner/Info.plist file.

...
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Your own description of the purpose.</string>
...

Usage #

The library is organised around a few base entities, which are:

  • BleManager
  • Peripheral
  • Service
  • Characteristic
  • Descriptor

You have to create an instance BleManager and initialise underlying native resources. Using that instance you then obtain an instance of Peripheral, which can be used to run operations on the corresponding peripheral.

All operations passing the Dart-native bridge are asynchronous, hence all operations in the plugin return either Future or Stream.

For more informations, see REFERENCE.

Notice: this library will not handle any permissions for you. To be able to scan for peripherals on Android you need ACCESS_FINE_LOCATION according to Android Developer Guide.

Initialising #

BleManager bleManager = BleManager();
await bleManager.createClient(); //ready to go!
// your peripheral logic
bleManager.destroyClient(); //remember to release native resources when you're done!

Following snippets assume the library has been initialised.

Handling Bluetooth adapter state #

enum BluetoothState {
  UNKNOWN,
  UNSUPPORTED,
  UNAUTHORIZED,
  POWERED_ON,
  POWERED_OFF,
  RESETTING,
}


bleManager.enableRadio(); //ANDROID-ONLY turns on BT. NOTE: doesn't check permissions
bleManager.disableRadio() //ANDROID-ONLY turns off BT. NOTE: doesn't check permissions
BluetoothState currentState = await bleManager.bluetoothState();
bleManager.observeBluetoothState().listen((btState) {
  print(btState);
  //do your BT logic, open different screen, etc.
});

Scanning for peripherals #

bleManager.startPeripheralScan(
  uuids: [
    "F000AA00-0451-4000-B000-000000000000",
  ],
).listen((scanResult) {
  //Scan one peripheral and stop scanning
  print("Scanned Peripheral ${scanResult.peripheral.name}, RSSI ${scanResult.rssi}");
  bleManager.stopPeripheralScan();
});

The snippet above starts peripheral scan and stops it after receiving first result. It filters the scan results to those that advertise a service with specified UUID.

NOTE: isConnectable and overflowServiceUuids fields of ScanResult are iOS-only and remain null on Android.

Connecting to peripheral #

First you must obtain a ScanResult from BleManager.startPeripheralScan().

Peripheral peripheral = scanResult.peripheral;
peripheral.observeConnectionState(emitCurrentValue: true, completeOnDisconnect: true)
  .listen((connectionState) {
    print("Peripheral ${scanResult.peripheral.identifier} connection state is $connectionState");
  });
await peripheral.connect();
bool connected = await peripheral.isConnected();
await peripheral.disconnectOrCancelConnection();

The snippet above starts observing the state of the connection to the peripheral, connects to it, checks if it's connected and then disconnects from it.

Transactions #

Methods that do not have counterpart with opposite effect and are asynchronous accept String transactionId as an optional argument, to allow the user to cancel such an operation. The Future returned to Dart will then finish with a BleError(BleErrorCode.operationCancelled...), but this will only discard the result of the operation, the operation itself will be executed either way.

For example, if I decided that I no longer want to run discovery on the selected peripheral:

//assuming peripheral is connected
peripheral.discoverAllServicesAndCharacteristics(transactionId: "discovery");
//will return operation cancelled error after calling the below
bleManager.cancelTransaction("discovery");

Each new operation with the same transactionId will cause the previous one to be cancelled with error, if it hasn't finished yet. If transactionId is set to null or it isn't specified at all, the library sets unique integer transactionId to such operation.

NOTE: Do not to set integers as transactionId as they are used by the library.

Obtaining characteristics #

To be able to operate on the peripheral, discovery of its services and characteristics must be run first.

//assuming peripheral is connected
await peripheral.discoverAllServicesAndCharacteristics();
List<Service> services = await peripheral.services(); //getting all services
List<Characteristic> characteristics1 = await peripheral.characteristics("F000AA00-0451-4000-B000-000000000000");
List<Characteristic> characteristics2 = await services.firstWhere(
  (service) => service.uuid == "F000AA00-0451-4000-B000-000000000000").characteristics();

//characteristics1 and characteristics2 have the same contents

Objects representing characteristics have a unique identifer, so they point to one specific characteristic, even if there are multiple service/characteristic uuid matches.

Manipulating characteristics #

Below are 3 methods of writing to a characteristic, which all result in the same effect given there's only one service with specified UUID and only one characteristic with specified UUID.

peripheral.writeCharacteristic(
  "F000AA00-0451-4000-B000-000000000000",
  "F000AA02-0451-4000-B000-000000000000",
  Uint8List.fromList([0]),
  false); //returns Characteristic to chain operations more easily

service.writeCharacteristic(
  "F000AA02-0451-4000-B000-000000000000",
  Uint8List.fromList([0]),
  false); //returns Characteristic to chain operations more easily

characteristic.write(Uint8List.fromList([0]), false); //returns void

Monitoring or reading a characteristic from Peripheral/Service level return CharacteristicWithValue object, which is Characteristic with additional Uint8List value property.

Descriptor operations #

List of descriptors from a single characteristic can be obtained in a similar fashion to a list of characteristics from a single service, either from Peripheral, Service or Characteristic object. Descriptors can be read/written from Peripheral, Service or Characteristic by supplying necessary UUIDs, or from Descriptor object.

Note: to enable monitoring of characteristic you should use characteristic.monitor() or (peripheral/service).monitorCharacteristic() instead of changing the value of the underlying descriptor yourself.

Facilitated by Frontside #

Frontside provided architectural advice and financial support for this library on behalf of Resideo.

Maintained by #

This library is maintained by Polidea

Contact us

Learn more about Polidea's BLE services.

Maintainers

TBD

License #

Copyright 2019 Polidea Sp. z o.o

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

More from Polidea #

Check out other Polidea's BLE libraries:

2.2.3 #

  • Fix issue with duplicated or malformed notification values

2.2.2 #

  • Fix issue with invalid characteristic value base64 coding when performing characteristic operations on iOS
  • Improve documentation

2.2.1 #

  • Hide private APIs
  • Add setup instructions to README
  • Add missing descriptor operations information to README
  • Moved permission_handler dependency to its place in example

2.2.0 #

  • NEW operations on descriptors
  • BREAKING FOR BLEMULATOR BLEmulator versions lower than 1.1.0 are not supported from this release
  • Support for AndroidX
  • Support for Swift 5
  • Lower iOS deployment target to 8.0

2.1.0 #

  • BREAKING ScanResult.AdvertisementData.ManufacturerData has changed type from Int8List to Uint8List
  • Fix issue with invalid value of manufacturer data in scan results
  • Fix issue with initialising plugin from a service without an active activity
  • Update README with information about permissions
  • Fix issue with default value of MTU when connecting to a peripheral on Android
  • Fix issue where first few notifications right after start of monitoring a characteristic could get lost

2.0.1 #

  • Fix issue with automatically generated transaction IDs.

2.0.0 #

  • Dart 2.0 support
  • BREAKING Completely new API. Consult README for instructions on how to use the new version.
  • Added BLEmulator support

example/lib/main.dart

import 'package:fimber/fimber.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ble_lib_example/devices_list/devices_bloc_provider.dart';
import 'package:flutter_ble_lib_example/devices_list/devices_list_view.dart';

import 'device_details/device_detail_view.dart';
import 'device_details/devices_details_bloc_provider.dart';

void main() {
  Fimber.plantTree(DebugTree());
  runApp(MyApp());
}

final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'FlutterBleLib example',
        theme: new ThemeData(
          primaryColor: new Color(0xFF0A3D91),
          accentColor: new Color(0xFFCC0000),
        ),
        initialRoute: "/",
        routes: <String, WidgetBuilder>{
          "/": (context) => DevicesBlocProvider(child: DevicesListScreen()),
          "/details": (context) => DeviceDetailsBlocProvider(child: DeviceDetailsView()),
        },
        navigatorObservers: [routeObserver],
      );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_ble_lib: ^2.2.3

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_ble_lib/flutter_ble_lib.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
89
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
94
Learn more about scoring.

We analyzed this package on Apr 7, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Format lib/descriptor.dart.

Run flutter format to format lib/descriptor.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
async ^2.2.0 2.4.1
collection ^1.14.11 1.14.11 1.14.12
flutter 0.0.0
Transitive dependencies
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test
mockito ^4.0.0
test ^1.5.3