Flutter Bluetooth

Bluetooth in Flutter:

FlutterBlue is a bluetooth plugin for  Fflutter, This is a  new mobile SDK to help developers build modern apps for iOS and Android to use bluetooth functionality.

FlutterBlue used for Cross-Platform Bluetooth :

FlutterBlue offer the more for  both platforms (iOS and Android). Using the FlutterBlue instance, we  can scan for and connect to nearby bluetooth devices.

Once the bluetooth  device  connectes, then the BluetoothDevice object can discover services  for Bluetooth services and  Bluetooth characteristic and also for bluetooth Descriptors. After Discovering and connecting the bluetooth device then it is used to directly interact with characteristics and descriptors.

Using the Bluetooth package as a library:

Adding Flutterblue Dependency package to Flutter:

Add this to your package’s pubspec.yaml file using below code:

dependencies:
flutter_blue: ^0.4.1

Installing The FlutterBlue Package into the Flutter:

Use the below code to install FlutterBlue package  from terminal editor:

$ flutter packages get

Importing FlutterBlue Dependency package into the flutter Dart Code:

use the below code to import into the dart code. without importing it if we use it will shows package not found exception.

import 'package:flutter_blue/flutter_blue.dart';

Using FlutterBlue in Flutter:

Obtain an instance or object of FlutterBlue.

FlutterBlue flutterBlue = FlutterBlue.instance;

Scan for a Bluetooth devices:

/// Start scanning
var scanSubscription = flutterBlue.scan().listen((scanResult) {
// do something with scan result
});

/// Stop scanning
scanSubscription.cancel();

Connect to a  Bluetooth device:

/// Create a connection to the device
var deviceConnection = flutterBlue.connect(device).listen((s) {
if(s == BluetoothDeviceState.connected) {
// device is connected, do something
}
});

/// Disconnect from device
deviceConnection.cancel();

Discovering Bluetooth services:

List<BluetoothService> services = await device.discoverServices();
services.forEach((service) {
// do something with service
});

Reading and writing characteristics:

// Reads all characteristics
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
List<int> value = await device.readCharacteristic(c);
print(value);
}

// Writes to a characteristic
await device.writeCharacteristic(c, [0x12, 0x34])

 

Reading and writing descriptors:

// Reads all descriptors
var descriptors = characteristic.descriptors;
for(BluetoothDescriptor d in descriptors) {
List<int> value = await device.readDescriptor(d);
print(value);
}

// Writes to a descriptor
await device.writeDescriptor(d, [0x12, 0x34])

Setting notifications:

await device.setNotifyValue(characteristic, true);
device.onValueChanged(characteristic).listen((value) {
// do something with new value
});

FlutterBlue API:

Android iOS Description
scan Starts a scan for Bluetooth Low Energy devices.
connect Establishes a connection to the Bluetooth Device.
state Gets the current state of the Bluetooth Adapter.
onStateChanged Stream of state changes for the Bluetooth Adapter.

BluetoothDevice API:

Android iOS Description
discoverServices Discovers services offered by the remote device as well as their characteristics and descriptors.
services Gets a list of services. Requires that discoverServices() has completed.
readCharacteristic Retrieves the value of a specified characteristic.
readDescriptor Retrieves the value of a specified descriptor.
writeCharacteristic Writes the value of a characteristic.
writeDescriptor Writes the value of a descriptor.
setNotifyValue Sets notifications or indications on the specified characteristic.
onValueChanged Notifies when the characteristic’s value has changed.
state Gets the current state of the Bluetooth Device.
onStateChanged Notifies of state changes for the Bluetooth Device.

Below is the Example to use Bluetooth functionality In Flutter:

 

 

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:flutter_blue_example/widgets.dart';

void main() {
runApp(new FlutterBlueApp());
}

class FlutterBlueApp extends StatefulWidget {
FlutterBlueApp({Key key, this.title}) : super(key: key);

final String title;

@override
_FlutterBlueAppState createState() => new _FlutterBlueAppState();
}

class _FlutterBlueAppState extends State<FlutterBlueApp> {
FlutterBlue _flutterBlue = FlutterBlue.instance;

/// Scanning
StreamSubscription _scanSubscription;
Map<DeviceIdentifier, ScanResult> scanResults = new Map();
bool isScanning = false;

/// State
StreamSubscription _stateSubscription;
BluetoothState state = BluetoothState.unknown;

/// Device
BluetoothDevice device;
bool get isConnected => (device != null);
StreamSubscription deviceConnection;
StreamSubscription deviceStateSubscription;
List<BluetoothService> services = new List();
Map<Guid, StreamSubscription> valueChangedSubscriptions = {};
BluetoothDeviceState deviceState = BluetoothDeviceState.disconnected;

@override
void initState() {
super.initState();
// Immediately get the state of FlutterBlue
_flutterBlue.state.then((s) {
setState(() {
state = s;
});
});

// Subscribe to state changes
_stateSubscription = _flutterBlue.onStateChanged().listen((s) {
setState(() {
state = s;
});
});
}

@override
void dispose() {
_stateSubscription?.cancel();
_stateSubscription = null;
_scanSubscription?.cancel();
_scanSubscription = null;
deviceConnection?.cancel();
deviceConnection = null;
super.dispose();
}

_startScan() {
_scanSubscription = _flutterBlue
.scan(
timeout: const Duration(seconds: 5),
/*withServices: [
new Guid('0000180F-0000-1000-8000-00805F9B34FB')
]*/
)

.listen((scanResult) {
print('localName: ${scanResult.advertisementData.localName}');
print(
'manufacturerData: ${scanResult.advertisementData.manufacturerData}');
print('serviceData: ${scanResult.advertisementData.serviceData}');
setState(() {
scanResults[scanResult.device.id] = scanResult;
});

}, onDone: _stopScan);

setState(() {
isScanning = true;
});
}

_stopScan() {
_scanSubscription?.cancel();
_scanSubscription = null;
setState(() {
isScanning = false;
});
}

_connect(BluetoothDevice d) async {
device = d;
// Connect to device
deviceConnection = _flutterBlue
.connect(device, timeout: const Duration(seconds: 4))
.listen(
null,
onDone: _disconnect,
);

// Update the connection state immediately
device.state.then((s) {
setState(() {
deviceState = s;
});
});

// Subscribe to connection changes
deviceStateSubscription = device.onStateChanged().listen((s) {
setState(() {
deviceState = s;
});

if (s == BluetoothDeviceState.connected) {
device.discoverServices().then((s) {
setState(() {
services = s;
});
});
}
});
}

_disconnect() {
// Remove all value changed listeners
valueChangedSubscriptions.forEach((uuid, sub) => sub.cancel());
valueChangedSubscriptions.clear();
deviceStateSubscription?.cancel();
deviceStateSubscription = null;
deviceConnection?.cancel();
deviceConnection = null;
setState(() {
device = null;
});
}

_readCharacteristic(BluetoothCharacteristic c) async {
await device.readCharacteristic(c);
setState(() {});
}

_writeCharacteristic(BluetoothCharacteristic c) async {
await device.writeCharacteristic(c, [0x12, 0x34],
type: CharacteristicWriteType.withResponse);
setState(() {});
}

_readDescriptor(BluetoothDescriptor d) async {
await device.readDescriptor(d);
setState(() {});
}

_writeDescriptor(BluetoothDescriptor d) async {
await device.writeDescriptor(d, [0x12, 0x34]);
setState(() {});
}

_setNotification(BluetoothCharacteristic c) async {
if (c.isNotifying) {
await device.setNotifyValue(c, false);
// Cancel subscription
valueChangedSubscriptions[c.uuid]?.cancel();
valueChangedSubscriptions.remove(c.uuid);
} else {
await device.setNotifyValue(c, true);
// ignore: cancel_subscriptions
final sub = device.onValueChanged(c).listen((d) {
setState(() {
print('onValueChanged $d');
});
});
// Add to map
valueChangedSubscriptions[c.uuid] = sub;
}

setState(() {});
}

_refreshDeviceState(BluetoothDevice d) async {
var state = await d.state;
setState(() {
deviceState = state;
print('State refreshed: $deviceState');
});
}

_buildScanningButton() {
if (isConnected || state != BluetoothState.on) {
return null;
}
if (isScanning) {
return new FloatingActionButton(
child: new Icon(Icons.stop),
onPressed: _stopScan,
backgroundColor: Colors.red,
);
} else {
return new FloatingActionButton(
child: new Icon(Icons.search), onPressed: _startScan);
}
}

_buildScanResultTiles() {
return scanResults.values
.map((r) => ScanResultTile(
result: r,
onTap: () => _connect(r.device),
))
.toList();
}

List<Widget> _buildServiceTiles() {
return services
.map(
(s) => new ServiceTile(
service: s,
characteristicTiles: s.characteristics
.map(
(c) => new CharacteristicTile(
characteristic: c,
onReadPressed: () => _readCharacteristic(c),
onWritePressed: () => _writeCharacteristic(c),
onNotificationPressed: () => _setNotification(c),
descriptorTiles: c.descriptors
.map(
(d) => new DescriptorTile(
descriptor: d,
onReadPressed: () => _readDescriptor(d),
onWritePressed: () =>
_writeDescriptor(d),
),
)
.toList(),
),
)
.toList(),
),
)
.toList();
}

_buildActionButtons() {
if (isConnected) {
return <Widget>[
new IconButton(
icon: const Icon(Icons.cancel),
onPressed: () => _disconnect(),
)
];
}
}

_buildAlertTile() {
return new Container(
color: Colors.redAccent,
child: new ListTile(
title: new Text(
'Bluetooth adapter is ${state.toString().substring(15)}',
style: Theme.of(context).primaryTextTheme.subhead,
),
trailing: new Icon(
Icons.error,
color: Theme.of(context).primaryTextTheme.subhead.color,
),
),
);
}

_buildDeviceStateTile() {
return new ListTile(
leading: (deviceState == BluetoothDeviceState.connected)
? const Icon(Icons.bluetooth_connected)
: const Icon(Icons.bluetooth_disabled),
title: new Text('Device is ${deviceState.toString().split('.')[1]}.'),
subtitle: new Text('${device.id}'),
trailing: new IconButton(
icon: const Icon(Icons.refresh),
onPressed: () => _refreshDeviceState(device),
color: Theme.of(context).iconTheme.color.withOpacity(0.5),
));
}

_buildProgressBarTile() {
return new LinearProgressIndicator();
}

@override
Widget build(BuildContext context) {
var tiles = new List<Widget>();
if (state != BluetoothState.on) {
tiles.add(_buildAlertTile());
}
if (isConnected) {
tiles.add(_buildDeviceStateTile());
tiles.addAll(_buildServiceTiles());
} else {
tiles.addAll(_buildScanResultTiles());
}
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('FlutterBlue'),
actions: _buildActionButtons(),
),
floatingActionButton: _buildScanningButton(),
body: new Stack(
children: <Widget>[
(isScanning) ? _buildProgressBarTile() : new Container(),
new ListView(
children: tiles,
)
],
),
),
);
}
}

 

Congratulations You Have Learned Using Bluetooth In Flutter For Both Android & IOS Devies with Exampe.

Leave a Reply

Categories