Bluetooth plugin for Flutter

Last update: Aug 13, 2022

pub package Chat


FlutterBlue



Introduction

FlutterBlue is a bluetooth plugin for Flutter, a new app SDK to help developers build modern multi-platform apps.

Alpha version

This library is actively developed alongside production apps, and the API will evolve as we continue our way to version 1.0.

Please be fully prepared to deal with breaking changes. This package must be tested on a real device.

Having trouble adapting to the latest API? I'd love to hear your use-case, please contact me.

Cross-Platform Bluetooth LE

FlutterBlue aims to offer the most from both platforms (iOS and Android).

Using the FlutterBlue instance, you can scan for and connect to nearby devices (BluetoothDevice). Once connected to a device, the BluetoothDevice object can discover services (BluetoothService), characteristics (BluetoothCharacteristic), and descriptors (BluetoothDescriptor). The BluetoothDevice object is then used to directly interact with characteristics and descriptors.

Usage

Obtain an instance

FlutterBlue flutterBlue = FlutterBlue.instance;

Scan for devices

// Start scanning
flutterBlue.startScan(timeout: Duration(seconds: 4));

// Listen to scan results
var subscription = flutterBlue.scanResults.listen((results) {
    // do something with scan results
    for (ScanResult r in results) {
        print('${r.device.name} found! rssi: ${r.rssi}');
    }
});

// Stop scanning
flutterBlue.stopScan();

Connect to a device

// Connect to the device
await device.connect();

// Disconnect from device
device.disconnect();

Discover services

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

Read and write characteristics

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

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

Read and write descriptors

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

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

Set notifications and listen to changes

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

Read the MTU and request larger size

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 is compatible only from version 19 of Android SDK so you should change this in android/app/build.gradle:

Android {
  defaultConfig {
     minSdkVersion: 19

Add permissions for Bluetooth

We need to add the permission to use Bluetooth and access location:

Android

In the android/app/src/main/AndroidManifest.xml let’s add:

	 <uses-permission android:name="android.permission.BLUETOOTH" />  
	 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />  
	 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
 <application

IOS

In the ios/Runner/Info.plist let’s add:

	<dict>  
	    <key>NSBluetoothAlwaysUsageDescription</key>  
	    <string>Need BLE permission</string>  
	    <key>NSBluetoothPeripheralUsageDescription</key>  
	    <string>Need BLE permission</string>  
	    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>  
	    <string>Need Location permission</string>  
	    <key>NSLocationAlwaysUsageDescription</key>  
	    <string>Need Location permission</string>  
	    <key>NSLocationWhenInUseUsageDescription</key>  
	    <string>Need Location permission</string>

For location permissions on iOS see more at: https://developer.apple.com/documentation/corelocation/requesting_authorization_for_location_services

Reference

FlutterBlue API

Android iOS Description
scan Starts a scan for Bluetooth Low Energy devices.
state Stream of state changes for the Bluetooth Adapter.
isAvailable Checks whether the device supports Bluetooth.
isOn Checks if Bluetooth functionality is turned on.

BluetoothDevice API

Android iOS Description
connect Establishes a connection to the device.
disconnect Cancels an active or pending connection to the device.
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.
state Stream of state changes for the Bluetooth Device.
mtu Stream of mtu size changes.
requestMtu Request to change the MTU for the device.

BluetoothCharacteristic API

Android iOS Description
read Retrieves the value of the characteristic.
write Writes the value of the characteristic.
setNotifyValue Sets notifications or indications on the characteristic.
value Stream of characteristic's value when changed.

BluetoothDescriptor API

Android iOS Description
read Retrieves the value of the descriptor.
write Writes the value of the descriptor.

Troubleshooting

When I scan using a service UUID filter, it doesn't find any devices.

Make sure the device is advertising which service UUID's it supports. This is found in the advertisement packet as UUID 16 bit complete list or UUID 128 bit complete list.

GitHub

https://github.com/pauldemarco/flutter_blue
Comments
  • 1. Getting multiple ( duplicate ) characteristics Notification data in Flutter_Blue 0.6

    In 0.6 v with Flutter 1.7.8 , following issue observed

    • On app restart, successfully connected to the device with set notification = true on a characteristics
    • after disconnecting ble communication from device got 'disconnect' event in notification listener myDevice.state.listen((deviceState) { ..... });
    • without resetting the app , if again connected to the device with set notification = true on characteristics Then it is observed that we get duplicate notification value always. (read_characteristics.value.listen((){.......})
    • This duplication increases if we repeat the above steps ( without resetting app ) e.g. if we connect to device 5 times without resetting app then get 10 times duplicate data every time. This happens on debug as well as release apk

    Please let us know how to handle this issue? what is the way to handle disconnect event to avoid duplicate notifications?

    Thanks , Gaurav

    Reviewed by GauravPatni at 2019-07-18 11:02
  • 2. error: package androidx.core.app does not exist

    Since the 0.6.3 update, i have this error message and i can't build my app :

    /home/***/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_blue-0.6.3/android/src/main/java/com/pauldemarco/flutter_blue/FlutterBluePlugin.java:43: error: package androidx.core.app does not exist import androidx.core.app.ActivityCompat;

    Reviewed by Jbz797 at 2019-10-18 08:58
  • 3. Is this repository dead?

    I've seem that the latest update on pub site was on october 2019 and here in git it has about 40+ pull requests. Most of them with no response from maintainers.

    Is that repository dead?

    If yes, can I suggest to transfer it's ownership?

    Reviewed by shinayser at 2020-03-04 15:47
  • 4. Issue with writeCharacteristic()

    I am trying to connect to an Adafruit nrf8001 hooked up to an Arduino. It uses the UART service with the UUID 6E400001-B5A3-F393-E0A9-E50E24DCCA9E as defined here. I communicates with the TX and RX characteristics. I can connect to the device perfectly fine, but when I try to write to the TX characteristic, I get the error:

    D/FlutterBluePlugin(20492): [onCharacteristicWrite] uuid: 6e400002-b5a3-f393-e0a9-e50e24dcca9e status: 128
    E/flutter (20492): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Exception: Failed to write the characteristic
    E/flutter (20492): #0      BluetoothDevice.writeCharacteristic.<anonymous closure> 
        ../…/src/bluetooth_device.dart:132
    ... full output below
    

    I set up my scanning for devices with:

    setState(() {
      _scanning = true;
    });
    _scanSubscription =
      flutterBlue.scan(timeout: Duration(minutes: 1)).listen((scanResult) {
        if (scanResult.advertisementData.connectable) {
          setState(() {
            scanResults[scanResult.device.id] = scanResult;
          });
        }
      }, onDone: _cancelScanning);
    

    and then I connect with:

    setState(() {
      _deviceConnection = flutterBlue.connect(device).listen((s) {
        if (s == BluetoothDeviceState.connected) {
          print('Connected');
          setState(() {
            _device = device;
            _connected = true;
            _statusMessage = 'Connected to Cycler';
          });
          _cancelScanning();
          _discoverServices();
        } else {
          print('Not Connected');
          print(s.toString());
        }
      });
    });
    

    I then find the UART service and related characteristics as follows:

    _discoverServices() {
      setState(() {
        _statusMessage = 'Discovering device services';
      });
      _device.discoverServices().then((s) {
        setState(() {
          _statusMessage = 'Services discovered';
          _deviceServices = s;
        });
        _findUART();
      });
    }
    
    _findUART() {
      if (_deviceServices != null && _deviceServices.isNotEmpty) {
        _deviceServices.forEach((service) {
          //servicesList.add(Text(service.uuid.toString()));
          if (service.uuid.toString().toLowerCase() ==
              '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'.toLowerCase()) {
            print('UART found');
            _uartService = service;
            service.characteristics.forEach((c) {
              if (c.uuid.toString().toLowerCase() ==
                  '6E400002-B5A3-F393-E0A9-E50E24DCCA9E'.toLowerCase()) {
                _tx = c;
                print('TX found');
              } else if (c.uuid.toString().toLowerCase() ==
                  '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'.toLowerCase()) {
                _rx = c;
                print('RX found');
              }
            });
          }
        });
      }
    }
    

    Then I have a button onPressed: linked to the method _sendTest

    _sendTest() async {
      final value = await _device.writeCharacteristic(_tx, [0x12, 0x34],
          type: CharacteristicWriteType.withResponse);
      print(value);
    }
    

    Using Flutter 1.2.1. Running on Samsung Galaxy S8. Please let me know if you need any more relevant information.

    Here's the full error:

    E/flutter (20492): #0      BluetoothDevice.writeCharacteristic.<anonymous closure> 
    ../…/src/bluetooth_device.dart:132
    E/flutter (20492): #1      _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (20492): #2      _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (20492): #3      _FutureListener.handleValue (dart:async/future_impl.dart:126:18)
    E/flutter (20492): #4      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639:45)
    E/flutter (20492): #5      Future._propagateToListeners (dart:async/future_impl.dart:668:32)
    E/flutter (20492): #6      Future._complete (dart:async/future_impl.dart:473:7)
    E/flutter (20492): #7      _cancelAndValue (dart:async/stream_pipe.dart:63:12)
    E/flutter (20492): #8      Stream.first.<anonymous closure> (dart:async/stream.dart:1170:11)
    E/flutter (20492): #9      _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (20492): #10     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (20492): #11     _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
    E/flutter (20492): #12     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
    E/flutter (20492): #13     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
    E/flutter (20492): #14     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:132:11)
    E/flutter (20492): #15     _WhereStream._handleData (dart:async/stream_pipe.dart:207:12)
    E/flutter (20492): #16     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:164:13)
    E/flutter (20492): #17     _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (20492): #18     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (20492): #19     _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
    E/flutter (20492): #20     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
    E/flutter (20492): #21     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
    E/flutter (20492): #22     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:132:11)
    E/flutter (20492): #23     _MapStream._handleData (dart:async/stream_pipe.dart:232:10)
    E/flutter (20492): #24     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:164:13)
    E/flutter (20492): #25     _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (20492): #26     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (20492): #27     _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
    E/flutter (20492): #28     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
    E/flutter (20492): #29     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
    E/flutter (20492): #30     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:132:11)
    E/flutter (20492): #31     _MapStream._handleData (dart:async/stream_pipe.dart:232:10)
    E/flutter (20492): #32     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:164:13)
    E/flutter (20492): #33     _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (20492): #34     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (20492): #35     _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
    E/flutter (20492): #36     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
    E/flutter (20492): #37     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
    E/flutter (20492): #38     _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:132:11)
    E/flutter (20492): #39     _WhereStream._handleData (dart:async/stream_pipe.dart:207:12)
    E/flutter (20492): #40     _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:164:13)
    E/flutter (20492): #41     _rootRunUnary (dart:async/zone.dart:1132:38)
    E/flutter (20492): #42     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
    E/flutter (20492): #43     _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
    E/flutter (20492): #44     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
    E/flutter (20492): #45     _DelayedData.perform (dart:async/stream_impl.dart:591:14)
    E/flutter (20492): #46     _StreamImplEvents.handleNext (dart:async/stream_impl.dart:707:11)
    E/flutter (20492): #47     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:667:7)
    E/flutter (20492): #48     _rootRun (dart:async/zone.dart:1120:38)
    E/flutter (20492): #49     _CustomZone.run (dart:async/zone.dart:1021:19)
    E/flutter (20492): #50     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
    E/flutter (20492): #51     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
    E/flutter (20492): #52     _rootRun (dart:async/zone.dart:1124:13)
    E/flutter (20492): #53     _CustomZone.run (dart:async/zone.dart:1021:19)
    E/flutter (20492): #54     _CustomZone.runGuarded (dart:async/zone.dar
    
    Reviewed by BradHacker at 2019-03-21 21:13
  • 5. Installation failed on osx

    On installation I get the following message and the installation fails. The protoc compiler is not found...

    ** /Users/satyajits/dev/flutter/bluetooth_example/Pods/!ProtoCompiler/protoc --objc_out=gen --proto_path=../protos ../protos/*.proto**

    However, the correct path is /Users/satyajits/dev/flutter/bluetooth_example/ios/Pods/!ProtoCompiler/protoc

    The difference is that the installation happens inside the ios folder of the flutter directory but somehow it is looking in the parent directory.

    Launching lib/main.dart on iPhone X in debug mode... Warning: CocoaPods recommended version 1.5.0 or greater not installed. Pods handling may fail on some projects involving plugins. To upgrade: brew upgrade cocoapods pod setup

    Running pod install... CocoaPods' output: ↳ Preparing

    Analyzing dependencies
    
    Inspecting targets to integrate
      Using `ARCHS` setting to build architectures of target `Pods-Runner`: (``)
    
    Fetching external sources
    -> Fetching podspec for `Flutter` from `.symlinks/flutter/ios`
    -> Fetching podspec for `flutter_blue` from `.symlinks/plugins/flutter_blue/ios`
    
    Resolving dependencies of `Podfile`
    
    Comparing resolved specification to the sandbox manifest
      A !ProtoCompiler
      A Flutter
      A Protobuf
      A flutter_blue
    
    Downloading dependencies
    
    -> Installing !ProtoCompiler (3.5.0)
      > Copying !ProtoCompiler from `/Users/satyajits/Library/Caches/CocoaPods/Pods/Release/!ProtoCompiler/3.5.0-3e9dc` to `Pods/!ProtoCompiler`
    
    -> Installing Flutter (1.0.0)
    
    -> Installing Protobuf (3.6.0)
      > Copying Protobuf from `/Users/satyajits/Library/Caches/CocoaPods/Pods/Release/Protobuf/3.6.0-0fc0a` to `Pods/Protobuf`
    
    -> Installing flutter_blue (0.0.1)
     > Running prepare command
       $ /bin/bash -c  set -e mkdir -p gen /Users/satyajits/dev/flutter/bluetooth_example/Pods/!ProtoCompiler/protoc         --objc_out=gen         --proto_path=../protos         ../protos/*.proto
    [!] /bin/bash -c 
    set -e
    mkdir -p gen
    /Users/satyajits/dev/flutter/bluetooth_example/Pods/!ProtoCompiler/protoc         --objc_out=gen         --proto_path=../protos         ../protos/*.proto
    
    /bin/bash: line 3: /Users/satyajits/dev/flutter/bluetooth_example/Pods/!ProtoCompiler/protoc: No such file or directory
    
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/executable.rb:69:in `execute_command'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/executable.rb:27:in `block in executable'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer/pod_source_preparer.rb:66:in `block (2 levels) in run_prepare_command'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer/pod_source_preparer.rb:60:in `chdir'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer/pod_source_preparer.rb:60:in `block in run_prepare_command'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/user_interface.rb:64:in `section'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer/pod_source_preparer.rb:59:in `run_prepare_command'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer/pod_source_preparer.rb:37:in `prepare!'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer/pod_source_installer.rb:61:in `install!'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:365:in `install_source_of_pod'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:330:in `block (2 levels) in install_pod_sources'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/user_interface.rb:85:in `titled_section'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:329:in `block in install_pod_sources'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:321:in `each'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:321:in `install_pod_sources'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:164:in `block in download_dependencies'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/user_interface.rb:64:in `section'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:162:in `download_dependencies'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/installer.rb:117:in `install!'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/command/install.rb:41:in `run'
    /Library/Ruby/Gems/2.3.0/gems/claide-1.0.2/lib/claide/command.rb:334:in `run'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/lib/cocoapods/command.rb:52:in `run'
    /Library/Ruby/Gems/2.3.0/gems/cocoapods-1.4.0/bin/pod:55:in `<top (required)>'
    /usr/local/bin/pod:22:in `load'
    /usr/local/bin/pod:22:in `<main>'
    

    Error output from CocoaPods: ↳ /bin/bash: line 3: /Users/satyajits/dev/flutter/bluetooth_example/Pods/!ProtoCompiler/protoc: No such file or directory

    [!] `<PBXGroup UUID=`97C146E51CF9000F007C117D`>` attempted to initialize an object with an unknown UUID. `CF3B75C9A7D2FA2A4C99F110` for attribute: `children`. This can be the result of a merge and  the unknown UUID is being discarded.
    

    Error running pod install Error launching application on iPhone X.

    Reviewed by ssarangi at 2018-06-19 01:41
  • 6. Advertising and turning hardware on/off

    Covers #47

    Unfortunately I brought a dependency for permissions that is giving me a bad time when compiling on iOS. Help is appreciated.

    Turning hw on/off should work on iOS but so far is untested. Advertising not implemented on iOS at all.

    Reviewed by fmatosqg at 2018-03-19 05:31
  • 7. Android X ScanResult empty list

    Hello community,

    I'm using Android X and Android 9 devices for testing. For Android X I've a huge problem. The ScanResults are always empty. On Android 9 Devices it shows me the correct ScanResults.

    Same Project. compileSDKVersion is 29. I also tried to change the permissions from ACCESS_COARSE_LOCATION to ACCESS_FINE_LOCATION, but no changes.

    Does someone have any idea how to fix it?

    Thank you in advance cheers, Kevin

    Reviewed by KevinRohn at 2020-01-24 07:57
  • 8. AdvertisementData contains empty values on iOS

    Hi,

    On iOS, I'm not seeing any data for the following properties on AdvertisementData in my ScanResult event stream handler:

    • localName
    • manufacturerData
    • serviceData

    I observed this to be consistent over ScanResults for responses for 19 different devices.

    localName returns an empty String, and manufacturerData and serviceData return an empty List<int>.

    Let me know if I can provide more details or if I can help in troubleshooting, debugging, or verifying a fix.

    Thanks.

    Reviewed by ryanhanks at 2018-03-19 03:07
  • 9. Queue GATT operations, refactor reply channels

    Bluetooth GATT operations cannot run concurrently, so they must be queued up to let old operations finish before a new one is triggered.

    Also, there is no need for a separate EventChannel for every kind of operation; answers (except for scanning) are now sent via the plugin's main MethodChannel.

    this mostly does #11, and fixes #30

    Reviewed by dturing at 2018-02-01 21:56
  • 10. Connnect BLE devcie error, under flutter v1.5.9 pre147

    I run the example under latest flutter (1.5.9 pre147) version, met an error.

    SCAN action is ok, the problem occurred while click CONNECT button.

    detail error message as below:

    D/BluetoothGatt( 4136): onClientConnectionState() - status=0 clientIf=5 device=10:CE:A9:2F:73:3F
    D/FlutterBluePlugin( 4136): [onConnectionStateChange] status: 0 newState: 2
    W/BluetoothGatt( 4136): Unhandled exception in callback
    W/BluetoothGatt( 4136): java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: Binder:4136_3
    W/BluetoothGatt( 4136): 	at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:605)
    W/BluetoothGatt( 4136): 	at io.flutter.embedding.engine.FlutterJNI.dispatchPlatformMessage(FlutterJNI.java:515)
    W/BluetoothGatt( 4136): 	at io.flutter.embedding.engine.dart.DartMessenger.send(DartMessenger.java:74)
    W/BluetoothGatt( 4136): 	at io.flutter.embedding.engine.dart.DartExecutor.send(DartExecutor.java:163)
    W/BluetoothGatt( 4136): 	at io.flutter.view.FlutterNativeView.send(FlutterNativeView.java:152)
    W/BluetoothGatt( 4136): 	at io.flutter.plugin.common.MethodChannel.invokeMethod(MethodChannel.java:95)
    W/BluetoothGatt( 4136): 	at io.flutter.plugin.common.MethodChannel.invokeMethod(MethodChannel.java:82)
    W/BluetoothGatt( 4136): 	at com.pauldemarco.flutterblue.FlutterBluePlugin$8.onConnectionStateChange(FlutterBluePlugin.java:757)
    W/BluetoothGatt( 4136): 	at android.bluetooth.BluetoothGatt$1$4.run(BluetoothGatt.java:262)
    W/BluetoothGatt( 4136): 	at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:770)
    W/BluetoothGatt( 4136): 	at android.bluetooth.BluetoothGatt.access$200(BluetoothGatt.java:39)
    W/BluetoothGatt( 4136): 	at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:257)
    W/BluetoothGatt( 4136): 	at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:71)
    W/BluetoothGatt( 4136): 	at android.os.Binder.execTransact(Binder.java:735)
    D/BluetoothManager( 4136): getConnectionState()
    D/BluetoothManager( 4136): getConnectedDevices
    I/flutter ( 4136): State refreshed: BluetoothDeviceState.connected
    D/BluetoothGatt( 4136): onConnectionUpdated() - Device=10:CE:A9:2F:73:3F interval=6 latency=0 timeout=500 status=0
    D/BluetoothGatt( 4136): onConnectionUpdated() - Device=10:CE:A9:2F:73:3F interval=36 latency=0 timeout=500 status=0
    D/BluetoothGatt( 4136): close()
    D/BluetoothGatt( 4136): unregisterApp() - mClientIf=5
    

    flutter_blue: 0.5(git: 6f6fa30d77c7d935)

    Any one can give some advice, thank you!

    Reviewed by guixue at 2019-05-08 09:06
  • 11. setNotifyValue on multiple characteristics simultaneously

    I am unable to setNotifyValue for multiple characteristics on the same device. It always crashes when I try to setNotifyValue on the second characteristic. The code to register to notifications looks like this:

    void registerNotifications(Store<AppState> store, BleDevice device,
        BluetoothCharacteristic humidityCharacteristic,
        BluetoothCharacteristic temperatureCharacteristic,) async {
      await device.device.setNotifyValue(humidityCharacteristic, true);
      device.device.onValueChanged(humidityCharacteristic).listen((value) {
        device.setHumidity(LittleEndianExtractor.extractDouble(value));
        store.dispatch(new BleDeviceNewValue(device: device));
      });
    
      await device.device.setNotifyValue(temperatureCharacteristic, true);
      device.device.onValueChanged(temperatureCharacteristic).listen((value) {
        device.setTemperature(LittleEndianExtractor.extractDouble(value));
        store.dispatch(new BleDeviceNewValue(device: device));
      });
    }
    

    I get the following runtime error message

    D/BluetoothGatt(19458): setCharacteristicNotification() - uuid: 00001235-b38d-4985-720e-0f993a68ee41 enable: true
    E/flutter (19458): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
    E/flutter (19458): PlatformException(set_notification_error, error when writing the descriptor, null)
    E/flutter (19458): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:547:7)
    E/flutter (19458): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:279:18)
    E/flutter (19458): <asynchronous suspension>
    E/flutter (19458): #2      BluetoothDevice.setNotifyValue (file:///home/psachs/.pub-cache/hosted/pub.dartlang.org/flutter_blue-0.3.3/lib/src/bluetooth_device.dart:170:41)
    E/flutter (19458): <asynchronous suspension>
    E/flutter (19458): #3      registerNotifications.<anonymous closure> (package:ble_scanner/middlerware/ble_middleware.dart:166:19)
    E/flutter (19458): #4      _RootZone.run (dart:async/zone.dart:1376:54)
    E/flutter (19458): #5      _FutureListener.handleWhenComplete (dart:async/future_impl.dart:151:18)
    E/flutter (19458): #6      Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:607:39)
    E/flutter (19458): #7      Future._propagateToListeners (dart:async/future_impl.dart:663:37)
    E/flutter (19458): #8      Future._complete (dart:async/future_impl.dart:471:7)
    E/flutter (19458): #9      _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
    E/flutter (19458): #10     BluetoothDevice.setNotifyValue (file:///home/psachs/.pub-cache/hosted/pub.dartlang.org/flutter_blue-0.3.3/lib/src/bluetooth_device.dart)
    E/flutter (19458): <asynchronous suspension>
    E/flutter (19458): #11     registerNotifications (package:ble_scanner/middlerware/ble_middleware.dart:165:17)
    E/flutter (19458): <asynchronous suspension>
    E/flutter (19458): #12     handleDeviceConnection.<anonymous closure>.<anonymous closure> (package:ble_scanner/middlerware/ble_middleware.dart:138:15)
    E/flutter (19458): #13     _RootZone.runUnary (dart:async/zone.dart:1381:54)
    E/flutter (19458): #14     _FutureListener.handleValue (dart:async/future_impl.dart:129:18)
    E/flutter (19458): #15     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:637:45)
    E/flutter (19458): #16     Future._propagateToListeners (dart:async/future_impl.dart:666:32)
    E/flutter (19458): #17     Future._complete (dart:async/future_impl.dart:471:7)
    E/flutter (19458): #18     _SyncCompleter.complete (dart:async/future_impl.dart:51:12)
    E/flutter (19458): #19     BluetoothDevice.discoverServices (file:///home/psachs/.pub-cache/hosted/pub.dartlang.org/flutter_blue-0.3.3/lib/src/bluetooth_device.dart)
    E/flutter (19458): <asynchronous suspension>
    E/flutter (19458): #20     handleDeviceConnection.<anonymous closure> (package:ble_scanner/middlerware/ble_middleware.dart:120:25)
    E/flutter (19458): #21     _RootZone.runUnaryGuarded (dart:async/zone.dart:1316:10)
    E/flutter (19458): #22     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:330:11)
    E/flutter (19458): #23     _DelayedData.perform (dart:async/stream_impl.dart:578:14)
    E/flutter (19458): #24     _StreamImplEvents.handleNext (dart:async/stream_impl.dart:694:11)
    E/flutter (19458): #25     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:654:7)
    E/flutter (19458): #26     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
    E/flutter (19458): #27     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
    
    Reviewed by psachs at 2018-04-23 15:13
  • 12. Support latest Flutter (3.0.5)

    • Update example to support flutter 3.0.5 (Deprecated API removed after v2.2 https://docs.flutter.dev/release/breaking-changes/2-2-deprecations#texttheme)
    • Update flutter-blue dependency rxdart to ^0.27.0
    Reviewed by GrayLand119 at 2022-08-11 09:13
  • 13. Update project files ios fix

    Add parameter "options:@{CBCentralManagerOptionShowPowerAlertKey: @0}" on create instance of "CBCentralManager". The message " APP_NAME would like to use bluetooth for new connections" every time the app starts Screen Shot 2022-07-29 at 18 06 18

    Reviewed by gomideDev at 2022-07-29 21:06
  • 14. Add `FlutterBlue.name` to get the human readable device name

    First - thanks for your wonderful project.

    This PR implements a new FlutterBlue.name property that will get the friendly bluetooth name of the local bluetooth adapter.

    I tested this with my android application and it seems to be working just fine.

    Please note that I did not test this under ios, Unfortunately I have no device to test it. The code is inferred from reading the ios docs, but I'm happy to just leave it unimplemented or add a comment if it's hard to test.

    Reviewed by mvo5 at 2022-07-16 20:02
  • 15. Flutter Blue can't write in characteristics

    I make simple app to write 2 variable on AT-09 BLE model wich connected with arduino The name of sensor is dddd when i use other app the BLE can read the values but my app don't work

    can someone correct my simple code please and explain the wrong :

    import 'package:flutter/material.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_blue/flutter_blue.dart';
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
    
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page', key: null,),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({required Key? key, required this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      FlutterBlue flutterBlue = FlutterBlue.instance;
    
      void _incrementCounter() {
        setState(() {
    
          _counter++;
          flutterBlue.startScan(timeout: Duration(seconds: 4));
    
    // Listen to scan results
          var subscription = flutterBlue.scanResults.listen((results) async {
            // do something with scan results
            for (ScanResult r in results) {
              String S=r.device.name.toString();
              if(S=='dddd '){
                print('*********************************');
                print('Find it ');
                print('*********************************');
                print('*********************************');
                print('${r.device.name}');
                await r.device.connect();
    
                List<BluetoothService> services =  await r.device.discoverServices() ;
                 services.forEach((service)  {
                   print(service.uuid.toString());
                  service.characteristics.forEach((characteristic) async {
                  print(characteristic.uuid.toString());
    
                  characteristic.write([0x12, 0x34]);
                    });
                });
    
              }
            }
          });
    
          print(subscription);
    
    // Stop scanning
          flutterBlue.stopScan();
    
        });
      }
    
      @override
      Widget build(BuildContext context) {
    
        return Scaffold(
          appBar: AppBar(
    
            title: Text(widget.title),
          ),
          body: Center(
    
            child: Column(
    
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.headline4,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    
    

    that is the output D/BluetoothAdapter(32728): isLeEnabled(): ON D/BluetoothLeScanner(32728): onScannerRegistered() - status=0 scannerId=6 mScannerId=0 I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd I/flutter (32728): ********************************* I/flutter (32728): Find it I/flutter (32728): ********************************* I/flutter (32728): ********************************* I/flutter (32728): dddd D/BluetoothAdapter(32728): isLeEnabled(): ON V/PhoneWindow(32728): DecorView setVisiblity: visibility = 4, Parent = [email protected], this = [email protected][MainActivity] I/GED (32728): ged_boost_gpu_freq, level 100, eOrigin 2, final_idx 2, oppidx_max 2, oppidx_min 0

    Reviewed by hasedr at 2022-07-11 10:52
  • 16. Android state always connected

    image

    android device state always return connected. is this bug? my test phone android12, iPhone was no problem.

    call device.disconnect() return stream disconnected but, change connected

    Reviewed by giroskii at 2022-07-06 08:21

Related

FlutterBleLib - A library for all your Bluetooth Low Energy needs in Flutter.
 FlutterBleLib - A library for all your Bluetooth Low Energy needs in Flutter.

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

Jun 10, 2022
Bluetooth Low Energy library for Flutter with support for simulating peripherals
Bluetooth Low Energy library for Flutter with support for simulating peripherals

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

Aug 7, 2022
A Flutter Template to communicate with an esp32 over bluetooth

Flutter Esp32 Bluetooth Template Changes in android/ [1 if you take the code to an other project, 2 still nessesarely]: Change minSdkVersion from 16 t

Aug 11, 2022
Aug 3, 2022
This flutter app will help you to connect to Bluetooth Devices (like, HC-05)
This flutter app will help you to connect to Bluetooth Devices (like, HC-05)

Flutter Bluetooth NOTE: This is the updated version of the app (using flutter_bluetooth_serial 0.2.2). This version has much fewer bugs and provides a

Jun 5, 2022
Flutter basic implementation for Classical Bluetooth (only RFCOMM for now)
Flutter basic implementation for Classical Bluetooth (only RFCOMM for now)

flutter_bluetooth_serial Flutter basic implementation for Classical Bluetooth (only RFCOMM for now). Features The first goal of this project, started

Apr 13, 2022
I have created app to connect printer with bluetooth. And I already fix library bugs

flutter_bluetooth_printer A new Flutter application. Getting Started This project is a starting point for a Flutter application. A few resources to ge

May 11, 2022
A project to get data from a fitbit device using bluetooth

Flutter 2 Boilerplate (version 1.3.0) A boilerplate project created in flutter. Boilerplate supports both web and mobile. VSCode is recommended in thi

Dec 16, 2021
EI Blue - Edge Impulse Data Capture Over Bluetooth

EI Blue - Edge Impulse Data Capture Over Bluetooth Purpose of this project is to enable embedded engineers to collect data from bluetooth enabled micr

Apr 16, 2022
Flutter beacons plugin for Android and iOS.

Beacons Flutter plugin to work with beacons. Supports Android API 16+ and iOS 8+. Features: Automatic permission management Ranging Monitoring (includ

Mar 10, 2022
Flutter NFC reader plugin for iOS and Android
Flutter NFC reader plugin for iOS and Android

Flutter NFC Reader & Writer A new flutter plugin to help developers looking to use internal hardware inside iOS or Android devices for reading and wri

Aug 15, 2022
A Flutter plugin for turning your device into a beacon.

Beacon Broadcast plugin for Flutter A Flutter plugin for turning your device into a beacon. Usage To use this plugin, add beacon_broadcast as a depend

Jun 28, 2022
Flutter plugin for accessing the NFC features on Android and iOS.

nfc_manager Flutter plugin for accessing the NFC features on Android and iOS. Note: This plugin depends on NFCTagReaderSession (requires iOS 13.0 or l

Jul 29, 2022
Flutter library that handles BLE operations for multiple devices.

Flutter reactive BLE library Flutter library that handles BLE operations for multiple devices. Usage The reactive BLE lib supports the following: BLE

Aug 13, 2022
Ready for Building Production-Ready Healthcare/ Doctor Consult Android and iOS app UI using Flutter.
Ready for Building Production-Ready Healthcare/ Doctor Consult Android and iOS app UI using Flutter.

Production-Ready Doctor Consultant App - Flutter UI Watch it on YouTube Packages we are using: flutter_svg: link Complete Source code (Patreon) In thi

Aug 2, 2022
ESC/POS (thermal, receipt) printing for Flutter & Dart (Android/iOS)
ESC/POS (thermal, receipt) printing for Flutter & Dart (Android/iOS)

esc_pos_bluetooth The library allows to print receipts using a Bluetooth printer. For WiFi/Ethernet printers, use esc_pos_printer library. TODO (PRs a

Aug 6, 2022
Bluetooth plugin for Flutter
Bluetooth plugin for Flutter

Introduction FlutterBlue is a bluetooth plugin for Flutter, a new app SDK to help developers build modern multi-platform apps. Alpha version This libr

Aug 13, 2022
Using Bluetooth plugin in Flutter (flutter_bluetooth_serial)
Using Bluetooth plugin in Flutter (flutter_bluetooth_serial)

Flutter Bluetooth NOTE: This is the updated version of the app (using flutter_bluetooth_serial 0.2.2). This version has much fewer bugs and provides a

Aug 6, 2022
FlutterBleLib - A library for all your Bluetooth Low Energy needs in Flutter.
 FlutterBleLib - A library for all your Bluetooth Low Energy needs in Flutter.

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

Jun 10, 2022
Bluetooth Low Energy library for Flutter with support for simulating peripherals
Bluetooth Low Energy library for Flutter with support for simulating peripherals

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

Aug 7, 2022