// // flutter bluetooth demo with provider plugin // // if you're having problem connecting, quit the app // turn off bluetooth on the tablet/phone // turn on bluetooth on the tablet/phone // it always works for me // // add to pubspec.yaml // provider: ^4.0.5+1 // flutter_blue: ^0.7.2 // // in file anroid/app/build.gradle // line 42 - change minSdkVersion to at least 19 // //////////////////////// main. dart /////////////////////// import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import './notify_value.dart'; import './home.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext bc) => MaterialApp( home: MultiProvider( providers: [ ChangeNotifierProvider(create:(_) => NotifyValue()) ], child: Home(), ) ); } //////////////////////// home.dart //////////////////////// import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import './notify_value.dart'; import './ble.dart'; class Home extends StatefulWidget { const Home({ Key key }) : super(key: key); @override HomeState createState() => HomeState(); } class HomeState extends State { String note = "bluetooth demo, if you're having problem\n" + "connecting, quit the program, then turn on/off\n" + "bluetooth settings on the table/phone, then\n" + "start the program again."; Ble ble; @override initState(){ super.initState(); ble = Ble(context); } @override Widget build(BuildContext context) { String data = Provider.of(context).value; return Scaffold( body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 50), Text(note), SizedBox(height: 50), Text("searching for: ${Ble.deviceName}"), SizedBox(height: 20), Text("service UUID: ${Ble.serviceUuid}"), SizedBox(height: 20), Text("characteristic UUID: ${Ble.charUuid}"), SizedBox(height: 30), Text(data, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), ],), ); } } /////////////////////// ble.dart ////////////////////////// import 'package:flutter/material.dart'; import 'package:flutter_blue/flutter_blue.dart'; import 'package:provider/provider.dart'; import './notify_value.dart'; class Ble { static String deviceName = "Adafruit Bluefruit LE"; static String serviceUuid = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; static String charUuid = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"; BuildContext bcArg; Ble(BuildContext this.bcArg) { // start scan //Provider.of(bcArg, listen: false).setData("Scanning..."); FlutterBlue.instance .startScan(timeout: Duration(seconds: 6)) .whenComplete(() { FlutterBlue.instance.stopScan(); _scanResult(); }); } // check scan result _scanResult() { FlutterBlue.instance.scanResults.first.then((element) { element.forEach((value) { if (value.device.name == deviceName) { Provider.of(bcArg, listen: false).setData("Found device: $deviceName"); _connectDevice(value.device); } }); }); } // conect do device _connectDevice(BluetoothDevice _device)async { try { await _device.connect(); _discoverServices(_device); } catch (e) { if (e.code != 'already_connected') { throw e; } } } _discoverServices(BluetoothDevice _device) async { List services = await _device.discoverServices(); services.forEach((service) { if (service.uuid.toString() == serviceUuid) { Provider.of(bcArg, listen: false).setData("Found service: $serviceUuid"); service.characteristics.forEach((c) { if (c.uuid.toString() == charUuid) { Provider.of(bcArg, listen: false).setData("Found char: $charUuid"); _handleNotifyChar(c); } }); } }); } _handleNotifyChar(BluetoothCharacteristic bc) async { await bc.setNotifyValue(true); bc.value.listen((data){ Provider.of(bcArg, listen: false).setData(String.fromCharCodes(data)); }); } } /////////////////////// notify_value.dart /////////////////// import 'package:flutter/material.dart'; class NotifyValue with ChangeNotifier { String _value = ""; String get value => _value; NotifyValue() { _value = "no data"; } void setData(String newValue) { _value = newValue; notifyListeners(); } }