Advertisement
rajath_pai

fixed error flutter blue

Aug 4th, 2021
1,176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Dart 19.95 KB | None | 0 0
  1. ___________________________
  2. //main.dart
  3. ___________________________
  4. // Copyright 2017, Paul DeMarco.
  5. // All rights reserved. Use of this source code is governed by a
  6. // BSD-style license that can be found in the LICENSE file.
  7.  
  8. import 'dart:async';
  9. import 'dart:math';
  10.  
  11. import 'package:flutter/material.dart';
  12. import 'package:flutter_blue/flutter_blue.dart';
  13. import 'package:flutter_blue_example/widgets.dart';
  14.  
  15. void main() {
  16.   runApp(FlutterBlueApp());
  17. }
  18.  
  19. class FlutterBlueApp extends StatelessWidget {
  20.   @override
  21.   Widget build(BuildContext context) {
  22.     return MaterialApp(
  23.       color: Colors.lightBlue,
  24.       home: StreamBuilder<BluetoothState>(
  25.           stream: FlutterBlue.instance.state,
  26.           initialData: BluetoothState.unknown,
  27.           builder: (c, snapshot) {
  28.             final state = snapshot.data;
  29.             if (state == BluetoothState.on) {
  30.               return FindDevicesScreen();
  31.             }
  32.             return BluetoothOffScreen(state: state);
  33.           }),
  34.     );
  35.   }
  36. }
  37.  
  38. class BluetoothOffScreen extends StatelessWidget {
  39.   const BluetoothOffScreen({Key? key, this.state}) : super(key: key);
  40.  
  41.   final BluetoothState? state;
  42.  
  43.   @override
  44.   Widget build(BuildContext context) {
  45.     return Scaffold(
  46.       backgroundColor: Colors.lightBlue,
  47.       body: Center(
  48.         child: Column(
  49.           mainAxisSize: MainAxisSize.min,
  50.           children: <Widget>[
  51.             Icon(
  52.               Icons.bluetooth_disabled,
  53.               size: 200.0,
  54.               color: Colors.white54,
  55.             ),
  56.             Text(
  57.               'Bluetooth Adapter is ${state != null ? state.toString().substring(15) : 'not available'}.',
  58.               style: Theme.of(context).primaryTextTheme.subtitle1?.copyWith(color: Colors.white),
  59.             ),
  60.           ],
  61.         ),
  62.       ),
  63.     );
  64.   }
  65. }
  66.  
  67. class FindDevicesScreen extends StatelessWidget {
  68.   @override
  69.   Widget build(BuildContext context) {
  70.     return Scaffold(
  71.       appBar: AppBar(
  72.         title: Text('Find Devices'),
  73.       ),
  74.       body: RefreshIndicator(
  75.         onRefresh: () =>
  76.             FlutterBlue.instance.startScan(timeout: Duration(seconds: 4)),
  77.         child: SingleChildScrollView(
  78.           child: Column(
  79.             children: <Widget>[
  80.               StreamBuilder<List<BluetoothDevice>>(
  81.                 stream: Stream.periodic(Duration(seconds: 2))
  82.                     .asyncMap((_) => FlutterBlue.instance.connectedDevices),
  83.                 initialData: [],
  84.                 builder: (c, snapshot) => Column(
  85.                   children: snapshot.data!
  86.                       .map((d) => ListTile(
  87.                             title: Text(d.name),
  88.                             subtitle: Text(d.id.toString()),
  89.                             trailing: StreamBuilder<BluetoothDeviceState>(
  90.                               stream: d.state,
  91.                               initialData: BluetoothDeviceState.disconnected,
  92.                               builder: (c, snapshot) {
  93.                                 if (snapshot.data ==
  94.                                     BluetoothDeviceState.connected) {
  95.                                   return ElevatedButton(
  96.                                     child: Text('OPEN'),
  97.                                     onPressed: () => Navigator.of(context).push(
  98.                                         MaterialPageRoute(
  99.                                             builder: (context) =>
  100.                                                 DeviceScreen(device: d))),
  101.                                   );
  102.                                 }
  103.                                 return Text(snapshot.data.toString());
  104.                               },
  105.                             ),
  106.                           ))
  107.                       .toList(),
  108.                 ),
  109.               ),
  110.               StreamBuilder<List<ScanResult>>(
  111.                 stream: FlutterBlue.instance.scanResults,
  112.                 initialData: [],
  113.                 builder: (c, snapshot) => Column(
  114.                   children: snapshot.data!
  115.                       .map(
  116.                         (r) => ScanResultTile(
  117.                           result: r,
  118.                           onTap: () => Navigator.of(context)
  119.                               .push(MaterialPageRoute(builder: (context) {
  120.                             r.device.connect();
  121.                             return DeviceScreen(device: r.device);
  122.                           })),
  123.                         ),
  124.                       )
  125.                       .toList(),
  126.                 ),
  127.               ),
  128.             ],
  129.           ),
  130.         ),
  131.       ),
  132.       floatingActionButton: StreamBuilder<bool>(
  133.         stream: FlutterBlue.instance.isScanning,
  134.         initialData: false,
  135.         builder: (c, snapshot) {
  136.           if (snapshot.data!) {
  137.             return FloatingActionButton(
  138.               child: Icon(Icons.stop),
  139.               onPressed: () => FlutterBlue.instance.stopScan(),
  140.               backgroundColor: Colors.red,
  141.             );
  142.           } else {
  143.             return FloatingActionButton(
  144.                 child: Icon(Icons.search),
  145.                 onPressed: () => FlutterBlue.instance
  146.                     .startScan(timeout: Duration(seconds: 4)));
  147.           }
  148.         },
  149.       ),
  150.     );
  151.   }
  152. }
  153.  
  154. class DeviceScreen extends StatelessWidget {
  155.   const DeviceScreen({Key? key, required this.device}) : super(key: key);
  156.  
  157.   final BluetoothDevice device;
  158.  
  159.   List<int> _getRandomBytes() {
  160.     final math = Random();
  161.     return [
  162.       math.nextInt(255),
  163.       math.nextInt(255),
  164.       math.nextInt(255),
  165.       math.nextInt(255)
  166.     ];
  167.   }
  168.  
  169.   List<Widget> _buildServiceTiles(List<BluetoothService> services) {
  170.     return services
  171.         .map(
  172.           (s) => ServiceTile(
  173.             service: s,
  174.             characteristicTiles: s.characteristics
  175.                 .map(
  176.                   (c) => CharacteristicTile(
  177.                     characteristic: c,
  178.                     onReadPressed: () => c.read(),
  179.                     onWritePressed: () async {
  180.                       await c.write(_getRandomBytes(), withoutResponse: true);
  181.                       await c.read();
  182.                     },
  183.                     onNotificationPressed: () async {
  184.                       await c.setNotifyValue(!c.isNotifying);
  185.                       await c.read();
  186.                     },
  187.                     descriptorTiles: c.descriptors
  188.                         .map(
  189.                           (d) => DescriptorTile(
  190.                             descriptor: d,
  191.                             onReadPressed: () => d.read(),
  192.                             onWritePressed: () => d.write(_getRandomBytes()),
  193.                           ),
  194.                         )
  195.                         .toList(),
  196.                   ),
  197.                 )
  198.                 .toList(),
  199.           ),
  200.         )
  201.         .toList();
  202.   }
  203.  
  204.   @override
  205.   Widget build(BuildContext context) {
  206.     return Scaffold(
  207.       appBar: AppBar(
  208.         title: Text(device.name),
  209.         actions: <Widget>[
  210.           StreamBuilder<BluetoothDeviceState>(
  211.             stream: device.state,
  212.             initialData: BluetoothDeviceState.connecting,
  213.             builder: (c, snapshot) {
  214.               VoidCallback? onPressed;
  215.               String text;
  216.               switch (snapshot.data) {
  217.                 case BluetoothDeviceState.connected:
  218.                   onPressed = () => device.disconnect();
  219.                   text = 'DISCONNECT';
  220.                   break;
  221.                 case BluetoothDeviceState.disconnected:
  222.                   onPressed = () => device.connect();
  223.                   text = 'CONNECT';
  224.                   break;
  225.                 default:
  226.                   onPressed = null;
  227.                   text = snapshot.data.toString().substring(21).toUpperCase();
  228.                   break;
  229.               }
  230.               return TextButton(
  231.                   onPressed: onPressed,
  232.                   child: Text(
  233.                     text,
  234.                     style: Theme.of(context)
  235.                         .primaryTextTheme
  236.                         .button
  237.                         ?.copyWith(color: Colors.white),
  238.                   ));
  239.             },
  240.           )
  241.         ],
  242.       ),
  243.       body: SingleChildScrollView(
  244.         child: Column(
  245.           children: <Widget>[
  246.             StreamBuilder<BluetoothDeviceState>(
  247.               stream: device.state,
  248.               initialData: BluetoothDeviceState.connecting,
  249.               builder: (c, snapshot) => ListTile(
  250.                 leading: (snapshot.data == BluetoothDeviceState.connected)
  251.                     ? Icon(Icons.bluetooth_connected)
  252.                     : Icon(Icons.bluetooth_disabled),
  253.                 title: Text(
  254.                     'Device is ${snapshot.data.toString().split('.')[1]}.'),
  255.                 subtitle: Text('${device.id}'),
  256.                 trailing: StreamBuilder<bool>(
  257.                   stream: device.isDiscoveringServices,
  258.                   initialData: false,
  259.                   builder: (c, snapshot) => IndexedStack(
  260.                     index: snapshot.data! ? 1 : 0,
  261.                     children: <Widget>[
  262.                       IconButton(
  263.                         icon: Icon(Icons.refresh),
  264.                         onPressed: () => device.discoverServices(),
  265.                       ),
  266.                       IconButton(
  267.                         icon: SizedBox(
  268.                           child: CircularProgressIndicator(
  269.                             valueColor: AlwaysStoppedAnimation(Colors.grey),
  270.                           ),
  271.                           width: 18.0,
  272.                           height: 18.0,
  273.                         ),
  274.                         onPressed: null,
  275.                       )
  276.                     ],
  277.                   ),
  278.                 ),
  279.               ),
  280.             ),
  281.             StreamBuilder<int>(
  282.               stream: device.mtu,
  283.               initialData: 0,
  284.               builder: (c, snapshot) => ListTile(
  285.                 title: Text('MTU Size'),
  286.                 subtitle: Text('${snapshot.data} bytes'),
  287.                 trailing: IconButton(
  288.                   icon: Icon(Icons.edit),
  289.                   onPressed: () => device.requestMtu(223),
  290.                 ),
  291.               ),
  292.             ),
  293.             StreamBuilder<List<BluetoothService>>(
  294.               stream: device.services,
  295.               initialData: [],
  296.               builder: (c, snapshot) {
  297.                 return Column(
  298.                   children: _buildServiceTiles(snapshot.data!),
  299.                 );
  300.               },
  301.             ),
  302.           ],
  303.         ),
  304.       ),
  305.     );
  306.   }
  307. }
  308.  
  309.  
  310. ___________________________
  311. //widgets.dart
  312. ___________________________
  313.  
  314. // Copyright 2017, Paul DeMarco.
  315. // All rights reserved. Use of this source code is governed by a
  316. // BSD-style license that can be found in the LICENSE file.
  317.  
  318. import 'package:flutter/material.dart';
  319. import 'package:flutter_blue/flutter_blue.dart';
  320.  
  321. class ScanResultTile extends StatelessWidget {
  322.   const ScanResultTile({Key? key, required this.result, this.onTap})
  323.       : super(key: key);
  324.  
  325.   final ScanResult result;
  326.   final VoidCallback? onTap;
  327.  
  328.   Widget _buildTitle(BuildContext context) {
  329.     if (result.device.name.length > 0) {
  330.       return Column(
  331.         mainAxisAlignment: MainAxisAlignment.start,
  332.         crossAxisAlignment: CrossAxisAlignment.start,
  333.         children: <Widget>[
  334.           Text(
  335.             result.device.name,
  336.             overflow: TextOverflow.ellipsis,
  337.           ),
  338.           Text(
  339.             result.device.id.toString(),
  340.             style: Theme.of(context).textTheme.caption,
  341.           )
  342.         ],
  343.       );
  344.     } else {
  345.       return Text(result.device.id.toString());
  346.     }
  347.   }
  348.  
  349.   Widget _buildAdvRow(BuildContext context, String title, String value) {
  350.     return Padding(
  351.       padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 4.0),
  352.       child: Row(
  353.         crossAxisAlignment: CrossAxisAlignment.start,
  354.         children: <Widget>[
  355.           Text(title, style: Theme.of(context).textTheme.caption),
  356.           SizedBox(
  357.             width: 12.0,
  358.           ),
  359.           Expanded(
  360.             child: Text(
  361.               value,
  362.               style: Theme.of(context)
  363.                   .textTheme
  364.                   .caption
  365.                   ?.apply(color: Colors.black),
  366.               softWrap: true,
  367.             ),
  368.           ),
  369.         ],
  370.       ),
  371.     );
  372.   }
  373.  
  374.   String getNiceHexArray(List<int> bytes) {
  375.     return '[${bytes.map((i) => i.toRadixString(16).padLeft(2, '0')).join(', ')}]'
  376.         .toUpperCase();
  377.   }
  378.  
  379.   String getNiceManufacturerData(Map<int, List<int>> data) {
  380.     if (data.isEmpty) {
  381.       return 'N/A';
  382.     }
  383.     List<String> res = [];
  384.     data.forEach((id, bytes) {
  385.       res.add(
  386.           '${id.toRadixString(16).toUpperCase()}: ${getNiceHexArray(bytes)}');
  387.     });
  388.     return res.join(', ');
  389.   }
  390.  
  391.   String getNiceServiceData(Map<String, List<int>> data) {
  392.     if (data.isEmpty) {
  393.       return 'N/A';
  394.     }
  395.     List<String> res = [];
  396.     data.forEach((id, bytes) {
  397.       res.add('${id.toUpperCase()}: ${getNiceHexArray(bytes)}');
  398.     });
  399.     return res.join(', ');
  400.   }
  401.  
  402.   @override
  403.   Widget build(BuildContext context) {
  404.     return ExpansionTile(
  405.       title: _buildTitle(context),
  406.       leading: Text(result.rssi.toString()),
  407.       trailing: ElevatedButton(
  408.         child: Text('CONNECT'),
  409.         style: ElevatedButton.styleFrom(primary: Colors.black),
  410.         onPressed: (result.advertisementData.connectable) ? onTap : null,
  411.       ),
  412.       children: <Widget>[
  413.         _buildAdvRow(
  414.             context, 'Complete Local Name', result.advertisementData.localName),
  415.         _buildAdvRow(context, 'Tx Power Level',
  416.             '${result.advertisementData.txPowerLevel ?? 'N/A'}'),
  417.         _buildAdvRow(context, 'Manufacturer Data',
  418.             getNiceManufacturerData(result.advertisementData.manufacturerData)),
  419.         _buildAdvRow(
  420.             context,
  421.             'Service UUIDs',
  422.             (result.advertisementData.serviceUuids.isNotEmpty)
  423.                 ? result.advertisementData.serviceUuids.join(', ').toUpperCase()
  424.                 : 'N/A'),
  425.         _buildAdvRow(context, 'Service Data',
  426.             getNiceServiceData(result.advertisementData.serviceData)),
  427.       ],
  428.     );
  429.   }
  430. }
  431.  
  432. class ServiceTile extends StatelessWidget {
  433.   final BluetoothService service;
  434.   final List<CharacteristicTile> characteristicTiles;
  435.  
  436.   const ServiceTile(
  437.       {Key? key, required this.service, required this.characteristicTiles})
  438.       : super(key: key);
  439.  
  440.   @override
  441.   Widget build(BuildContext context) {
  442.     if (characteristicTiles.length > 0) {
  443.       return ExpansionTile(
  444.         title: Column(
  445.           mainAxisAlignment: MainAxisAlignment.center,
  446.           crossAxisAlignment: CrossAxisAlignment.start,
  447.           children: <Widget>[
  448.             Text('Service'),
  449.             Text('0x${service.uuid.toString().toUpperCase().substring(4, 8)}',
  450.                 style: Theme.of(context).textTheme.bodyText1?.copyWith(
  451.                     color: Theme.of(context).textTheme.caption?.color))
  452.           ],
  453.         ),
  454.         children: characteristicTiles,
  455.       );
  456.     } else {
  457.       return ListTile(
  458.         title: Text('Service'),
  459.         subtitle:
  460.             Text('0x${service.uuid.toString().toUpperCase().substring(4, 8)}'),
  461.       );
  462.     }
  463.   }
  464. }
  465.  
  466. class CharacteristicTile extends StatelessWidget {
  467.   final BluetoothCharacteristic characteristic;
  468.   final List<DescriptorTile> descriptorTiles;
  469.   final VoidCallback? onReadPressed;
  470.   final VoidCallback? onWritePressed;
  471.   final VoidCallback? onNotificationPressed;
  472.  
  473.   const CharacteristicTile(
  474.       {Key? key,
  475.       required this.characteristic,
  476.       required this.descriptorTiles,
  477.       this.onReadPressed,
  478.       this.onWritePressed,
  479.       this.onNotificationPressed})
  480.       : super(key: key);
  481.  
  482.   @override
  483.   Widget build(BuildContext context) {
  484.     return StreamBuilder<List<int>>(
  485.       stream: characteristic.value,
  486.       initialData: characteristic.lastValue,
  487.       builder: (c, snapshot) {
  488.         final value = snapshot.data;
  489.         return ExpansionTile(
  490.           title: ListTile(
  491.             title: Column(
  492.               mainAxisAlignment: MainAxisAlignment.center,
  493.               crossAxisAlignment: CrossAxisAlignment.start,
  494.               children: <Widget>[
  495.                 Text('Characteristic'),
  496.                 Text(
  497.                     '0x${characteristic.uuid.toString().toUpperCase().substring(4, 8)}',
  498.                     style: Theme.of(context).textTheme.bodyText1?.copyWith(
  499.                         color: Theme.of(context).textTheme.caption?.color))
  500.               ],
  501.             ),
  502.             subtitle: Text(value.toString()),
  503.             contentPadding: EdgeInsets.all(0.0),
  504.           ),
  505.           trailing: Row(
  506.             mainAxisSize: MainAxisSize.min,
  507.             children: <Widget>[
  508.               IconButton(
  509.                 icon: Icon(
  510.                   Icons.file_download,
  511.                   color: Theme.of(context).iconTheme.color?.withOpacity(0.5),
  512.                 ),
  513.                 onPressed: onReadPressed,
  514.               ),
  515.               IconButton(
  516.                 icon: Icon(Icons.file_upload,
  517.                     color: Theme.of(context).iconTheme.color?.withOpacity(0.5)),
  518.                 onPressed: onWritePressed,
  519.               ),
  520.               IconButton(
  521.                 icon: Icon(
  522.                     characteristic.isNotifying
  523.                         ? Icons.sync_disabled
  524.                         : Icons.sync,
  525.                     color: Theme.of(context).iconTheme.color?.withOpacity(0.5)),
  526.                 onPressed: onNotificationPressed,
  527.               )
  528.             ],
  529.           ),
  530.           children: descriptorTiles,
  531.         );
  532.       },
  533.     );
  534.   }
  535. }
  536.  
  537. class DescriptorTile extends StatelessWidget {
  538.   final BluetoothDescriptor descriptor;
  539.   final VoidCallback? onReadPressed;
  540.   final VoidCallback? onWritePressed;
  541.  
  542.   const DescriptorTile(
  543.       {Key? key,
  544.       required this.descriptor,
  545.       this.onReadPressed,
  546.       this.onWritePressed})
  547.       : super(key: key);
  548.  
  549.   @override
  550.   Widget build(BuildContext context) {
  551.     return ListTile(
  552.       title: Column(
  553.         mainAxisAlignment: MainAxisAlignment.center,
  554.         crossAxisAlignment: CrossAxisAlignment.start,
  555.         children: <Widget>[
  556.           Text('Descriptor'),
  557.           Text('0x${descriptor.uuid.toString().toUpperCase().substring(4, 8)}',
  558.               style: Theme.of(context)
  559.                   .textTheme
  560.                   .bodyText1
  561.                   ?.copyWith(color: Theme.of(context).textTheme.caption?.color))
  562.         ],
  563.       ),
  564.       subtitle: StreamBuilder<List<int>>(
  565.         stream: descriptor.value,
  566.         initialData: descriptor.lastValue,
  567.         builder: (c, snapshot) => Text(snapshot.data.toString()),
  568.       ),
  569.       trailing: Row(
  570.         mainAxisSize: MainAxisSize.min,
  571.         children: <Widget>[
  572.           IconButton(
  573.             icon: Icon(
  574.               Icons.file_download,
  575.               color: Theme.of(context).iconTheme.color?.withOpacity(0.5),
  576.             ),
  577.             onPressed: onReadPressed,
  578.           ),
  579.           IconButton(
  580.             icon: Icon(
  581.               Icons.file_upload,
  582.               color: Theme.of(context).iconTheme.color?.withOpacity(0.5),
  583.             ),
  584.             onPressed: onWritePressed,
  585.           )
  586.         ],
  587.       ),
  588.     );
  589.   }
  590. }
  591.  
  592. class AdapterStateTile extends StatelessWidget {
  593.   const AdapterStateTile({Key? key, required this.state}) : super(key: key);
  594.  
  595.   final BluetoothState state;
  596.  
  597.   @override
  598.   Widget build(BuildContext context) {
  599.     return Container(
  600.       color: Colors.redAccent,
  601.       child: ListTile(
  602.         title: Text(
  603.           'Bluetooth adapter is ${state.toString().substring(15)}',
  604.           style: Theme.of(context).primaryTextTheme.subtitle1,
  605.         ),
  606.         trailing: Icon(
  607.           Icons.error,
  608.           color: Theme.of(context).primaryTextTheme.subtitle1?.color,
  609.         ),
  610.       ),
  611.     );
  612.   }
  613. }
  614.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement