下面的代码无论怎么实现都不是完美的

问题描述 投票:0回答:1

在flutter和webview中,如果要实现蓝牙连接,如果连接丢失,会立即进行蓝牙扫描和连接。最终目标是保持蓝牙连接始终在线。下面的代码无论怎么实现都不完美,总是扫描一段时间就中断。

import 'dart:async';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:webview_flutter/webview_flutter.dart';

import 'Tool.dart';

class AbcIndex extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _AbcIndexState();
}

class _AbcIndexState extends State<AbcIndex> {
  StreamController<String> dataStreamController = StreamController<String>();
  BluetoothConnectionState connectionState = BluetoothConnectionState.disconnected;
  StreamSubscription<String>? subscription;
  late WebViewController controller;

  @override
  void initState() {
    super.initState();
    initBluetooth();

    // Initialize WebView
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(NavigationDelegate(
        onProgress: (int progress) {},
        onPageFinished: (String url) {
          print("Page loaded: $url");

          subscription = dataStreamController.stream.listen((data) {
            // Process data received from the stream
            print('Received data from stream: $data');
            // Perform other operations, such as passing data to WebView
            String javascriptCode = 'updateData("$data")';
            // controller.runJavaScript(javascriptCode);
          }, onError: (error) {
            print('Error occurred in stream: $error');
          }, onDone: () {
            print('Stream has been closed');
          });
        },
        onWebResourceError: (error) {},
        onNavigationRequest: (request) {
          return NavigationDecision.navigate;
        },
      ))
      ..loadRequest(Uri.parse('http://192.168.1.2:3000'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //appBar: AppBar(title: const Text('Flutter Web View'),),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }

  void initBluetooth() async {
    _scanForDevices();
  }

  Future<void>  _scanForDevices() async {
    while (connectionState != BluetoothConnectionState.connected) {
      FlutterBluePlus.startScan(timeout: Duration(seconds: 4));

      try {
        await for (var results in FlutterBluePlus.scanResults) {
          // Process scan results
          for (var result in results) {
            if (result.device.name.startsWith("DeviceSN")) {
              // Output device information
              print("Device name: ${result.device.name}");
              print("Device id: ${result.device.id}");

              await connectToDevice(result.device);

              FlutterBluePlus.stopScan();
              break;
            }
          }
        }
      } catch (error) {
        print('Error occurred in scanResults stream: $error');
      }
    }
  }

  Future<void> connectToDevice(BluetoothDevice device) async {
    // Connect to the device
    await device.connect();

    // Listen to connection state changes
    device.state.listen((state) async {
      if (state == BluetoothConnectionState.connected) {
        // Connection successful, perform further operations
        print("Connected!");
        // Read device characteristics
        await readCharacteristics(device);
      } else {
        // Connection failed
        print("Bluetooth disconnected, rescanning...");
        await device.disconnect();
        await Future.delayed(Duration(seconds: 2));
        await _scanForDevices();
      }
      setState(() {
        connectionState = state;
      });
    });
  }

  Future<void> readCharacteristics(BluetoothDevice device) async {

    await device.discoverServices();

    print("device.servicesList");
    for (var service in device.servicesList!) {
      if (service?.serviceUuid.toString() == "0000180f-0000-1000-8000-00805f9b34fb") {
        print(service);
        var characters = service?.characteristics;

        for (var character in characters!) {
          if (character.characteristicUuid.toString() == "00002a19-0000-1000-8000-00805f9b34fb") {
            character.setNotifyValue(true);

            String fulhex = "";
            character.value.listen((hexList) {
              String hex = CharacterToHexStr(hexList);
              dataStreamController.add(hex );
            });
          }
        }
      }
    }
  }

  @override
  void dispose() {
    dataStreamController.close();
    subscription?.cancel();
    super.dispose();
  }

String CharacterToHexStr(List<int> hexList) {
  String hex = '';
  for(int value in hexList) {
    String hexValue = value.toRadixString(16).padLeft(2, '0');
    hex += hexValue;
  }
  return hex;
}
}


保持蓝牙连接在线

flutter webview bluetooth
1个回答
0
投票

我从几个不同的领域获取了这些内容,但它们可能会有所帮助:

连续扫描:一旦找到您要查找的设备,就应该停止扫描。连续扫描可能会导致连接问题。在您的代码中,一旦找到所需的设备,您就会正确地停止扫描。但是,您还应该在 FlutterBluePlus.stopScan(); 之后包含一个break语句。退出 for 循环。

await connectToDevice(result.device);
FlutterBluePlus.stopScan();
break;

重新连接之前断开连接:如果连接断开,最好在尝试重新连接之前显式断开设备连接。

if (state == BluetoothConnectionState.disconnected) {
    print("Bluetooth disconnected, rescanning...");
    await device.disconnect();
    await Future.delayed(Duration(seconds: 2));
    await _scanForDevices();
}

异常处理:蓝牙操作过程中,应妥善处理异常情况。例如,如果连接失败,connect() 方法可能会引发异常。您应该将此方法调用包装在 try-catch 块内以处理潜在的异常。

try {
    await device.connect();
} catch (e) {
    print(e.toString());
    // handle exception
}

检查设备可用性:确保蓝牙设备始终可用且位于范围内。如果设备超出范围或关闭,连接将会丢失。

管理资源:确保在不再需要任何打开的资源时将其关闭。例如,当小部件被释放时,您应该取消对设备状态的订阅。

@override
void dispose() {
    dataStreamController.close();
    subscription?.cancel();
    super.dispose();
}
© www.soinside.com 2019 - 2024. All rights reserved.