flutter_ttc_ble 0.0.3 copy "flutter_ttc_ble: ^0.0.3" to clipboard
flutter_ttc_ble: ^0.0.3 copied to clipboard

outdated

Android BLE(Bluetooth Low Energy) Flutter plugin.

example/lib/main.dart

import 'dart:async';
import 'dart:typed_data';

import 'package:convert/convert.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ttc_ble/flutter_ttc_ble.dart';
import 'package:permission_handler/permission_handler.dart';

import 'communication.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,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  List<BLEDevice> _dataList = <BLEDevice>[];
  Function _bleCallback;

  @override
  void initState() {
    super.initState();
    print('main -> initState()');
    WidgetsBinding.instance.addObserver(this);

    initPlatformState();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    //TODO BLE 插件初始化
    FlutterTtcBle.init();

    /// 添加蓝牙事件监听
    _bleCallback = (message) {
      if (message is Map<dynamic, dynamic>) {
        if (message.containsKey('event')) {
          switch (message['event']) {
            case 'bluetooth_state_changed':
              if (message['state'] == 'on') {
                print('main -> 蓝牙打开');
                _refresh(); //开始扫描
              }
              if (message['state'] == 'off') {
                print('main -> 蓝牙关闭');
              }
              break;
          }
        }
      }
      return;
    };
    FlutterTtcBle.addBLECallBack(_bleCallback);
    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;
  }

  @override
  void didChangeDependencies() {
    print('main -> didChangeDependencies()');
    super.didChangeDependencies();
  }

  @override
  void deactivate() {
    //当State对象从树中被移除时,会调用此回调。
    print('main -> deactivate()');
    super.deactivate();
  }

  @override
  void dispose() {
    //当State对象从树中被永久移除时调用,通常在此回调中释放资源。
    print('main -> dispose()');
    FlutterTtcBle.removeBLECallBack(_bleCallback);
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  //Flutter生命周期:https://blog.csdn.net/brycegao321/article/details/86583223
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print('main -> didChangeAppLifecycleState() - state=$state');
    if (state == AppLifecycleState.paused) {
      FlutterTtcBle.stopLeScan();
    }
    super.didChangeAppLifecycleState(state);
  }

  @override
  Widget build(BuildContext context) {
    //print('main -> build()');
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter BLE Demo V1.0'),
        ),
        body: RefreshIndicator(
          onRefresh: _refresh,
          child: ListView.separated(
            itemBuilder: (context, index) {
              return _buildRow(_dataList[index]);
            },
            itemCount: _dataList.length,
            separatorBuilder: (context, index) => Divider(
                thickness: 0.8, color: Color.fromARGB(0xff, 0xdd, 0xdd, 0xdd)),
          ),
        ),
      ),
    );
  }

  ///下拉刷新(扫描设备)
  Future<Null> _refresh() async {
    var scan = await _checkScan();
    if (!scan) return;

    setState(() {
      _dataList.clear();
    });

    FlutterTtcBle.startLeScan((device) {
      setState(() {
        //刷新UI要在setState()方法内进行
        //为了防止列表中设备重复,这里判断一下
        if (!_dataList.contains(device)) _dataList.add(device);
      });
      return;
    });

    await Future.delayed(Duration(seconds: 5), () {
      print('refresh() - delayed 5s');
      setState(() {
        //
      });
    });
  }

  ///安卓蓝牙扫描麻烦呀,扫描前得检查一通
  Future<bool> _checkScan() async {
    var isBluetoothEnabled = await FlutterTtcBle.isBluetoothEnabled();
    if (!isBluetoothEnabled) {
      print('请求打开蓝牙');
      FlutterTtcBle.requestEnableBluetooth();
      return false;
    }

    var isLocationEnabled = await Permission.location.serviceStatus.isEnabled;
    if (!isLocationEnabled) {
      print('请求打开位置服务');
      _showAlertDialog('扫描设备需要开启位置服务,点击“设置”,可开启位置服务。', '设置', () {
        FlutterTtcBle.requestEnableLocationService();
      });
      return false;
    }

    // Use location.
    //https://pub.dev/packages/permission_handler
    var status = await Permission.location.request();

    switch (status) {
      case PermissionStatus.denied:
        print('XXX 用户拒绝访问位置权限');
        return false;

      case PermissionStatus.granted:
        print('用户允许访问位置权限');
        return true;

      case PermissionStatus.permanentlyDenied: //Only supported on Android
        print('XXX 用户拒绝访问位置权限,且不再询问');
        _showAlertDialog('扫描设备需要位置权限,点击“设置”->“权限管理”,可开启位置权限。', '设置', () {
          openAppSettings();
        });
        return false;

      case PermissionStatus.restricted: //Only supported on iOS
        print('XXX restricted');
        break;

      case PermissionStatus.undetermined:
        print('尚未请求过位置权限');
        break;
    }
    return false;
  }

  ///加载列表项
  Widget _buildRow(BLEDevice device) {
    // 这里使用 Builder 避免异常:Navigator operation requested with a context that does not include a Navigator.
    // 参考 https://blog.csdn.net/nimeghbia/article/details/84388725

    return Builder(
      builder: (context) => new ListTile(
        title: new Text(
          device.name != null ? device.name : "Unknown Device",
        ),
        subtitle: new Text(
          '${device.deviceId}'
          '\nAdvertisData=${_advertisDataToString(device.advertisData)}'
          '\nServiceUUIDs=${device.advertisServiceUUIDs}'
          '\nServiceData=${_serviceDataToString(device.serviceData)}',
        ),
        onTap: () {
          _toCommPage(context, device);
        },
      ),
    );
  }

  String _advertisDataToString(Uint8List advertisData) {
    return advertisData == null ? "" : hex.encode(advertisData);
  }

  String _serviceDataToString(Map<String, Uint8List> serviceData) {
    StringBuffer sb = StringBuffer('{');
    int i = 0;
    serviceData.forEach((uuid, data) => (String uuid, Uint8List data) {
          sb.write("$uuid: ${hex.encode(data)}");
          if (i < serviceData.length - 1) {
            sb.write(', ');
          }
          i++;
        });
    sb.write('}');
    return sb.toString();
  }

  ///跳转到数据交互页面
  void _toCommPage(BuildContext context, BLEDevice device) async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (BuildContext context) => CommPage(device)),
    );

    print('从数据交互页面返回 $result');

    ///这是在页面底部显示一个弹出提示
    //Scaffold.of(context).showSnackBar(SnackBar(content: Text(result)));
    //TODO 监听平台消息
  }


  Future<void> _showAlertDialog(
      String message, String okText, Function okCallback) async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false, // user must tap button!
      builder: (BuildContext context) {
        return AlertDialog(
          content: Text(message),
          actions: <Widget>[
            FlatButton(
              child: Text('取消'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            FlatButton(
              child: Text(okText),
              onPressed: () {
                Navigator.of(context).pop();
                okCallback();
              },
            ),
          ],
        );
      },
    );
  }
}
11
likes
0
points
215
downloads

Publisher

unverified uploader

Weekly Downloads

Android BLE(Bluetooth Low Energy) Flutter plugin.

Homepage

License

unknown (license)

Dependencies

convert, flutter

More

Packages that depend on flutter_ttc_ble