Flutter iOS:无第三方包,通过Method Channel结合AppDelegate.swift检查蓝牙状态
解决Flutter iOS端通过Method Channel结合AppDelegate检查蓝牙状态的问题
原代码存在的问题
centralManager是方法内的局部变量,创建后立即判断状态时,CBCentralManager可能还未完成初始化,此时状态大概率是unknown,导致判断不准确- 未正确实现
CBCentralManagerDelegate的centralManagerDidUpdateState方法,无法接收蓝牙状态的异步更新 - 未保留
centralManager的类级实例,方法执行完毕后局部变量被释放,代理回调无法触发 - 使用了已废弃的
CBCentralManagerState枚举,应替换为CBManagerState
修正后的AppDelegate.swift代码
import UIKit import Flutter import CoreBluetooth @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, CBCentralManagerDelegate { // 将centralManager设为类属性,避免被释放 private var centralManager: CBCentralManager! // 保存Flutter回调,用于状态更新后返回结果 private var bluetoothStateResult: FlutterResult? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 初始化CBCentralManager,确保代理生效 centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: false]) // 注册Method Channel let controller: FlutterViewController = window?.rootViewController as! FlutterViewController let bluetoothChannel = FlutterMethodChannel(name: "app/bleState", binaryMessenger: controller.binaryMessenger) bluetoothChannel.setMethodCallHandler { [weak self] call, result in guard let self = self else { return } switch call.method { case "getBluetoothState": // 先检查当前状态,如果不是unknown直接返回 if self.centralManager.state != .unknown { result(self.centralManager.state == .poweredOn) } else { // 状态未确定,保存回调,等待代理返回 self.bluetoothStateResult = result } default: result(FlutterMethodNotImplemented) } } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // 实现代理方法,处理蓝牙状态更新 func centralManagerDidUpdateState(_ central: CBCentralManager) { // 如果有等待的回调,返回当前状态 if let result = bluetoothStateResult { result(central.state == .poweredOn) bluetoothStateResult = nil // 清空回调,避免重复调用 } } }
Flutter端调用代码示例
import 'package:flutter/services.dart'; class BluetoothChecker { static const MethodChannel _channel = MethodChannel('app/bleState'); static Future<bool> get isBluetoothEnabled async { try { final bool result = await _channel.invokeMethod('getBluetoothState'); return result; } on PlatformException catch (e) { print('获取蓝牙状态失败: ${e.message}'); return false; } } } // 使用示例 // bool enabled = await BluetoothChecker.isBluetoothEnabled;
关键说明
- 类级别的
centralManager确保实例不会被释放,代理回调能正常触发 - 处理
getBluetoothState调用时,先判断当前状态,若未初始化完成则保存回调,等待代理方法返回后再响应 - 使用最新的
CBManagerState枚举替代废弃的CBCentralManagerState - 增加
[weak self]避免循环引用
内容的提问来源于stack exchange,提问作者jos Sea
相关产品推荐
相关产品推荐

