You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
6.5 KiB
203 lines
6.5 KiB
import Flutter
|
|
import UIKit
|
|
|
|
public class SwiftBleServicePlugin: NSObject, FlutterPlugin, BleDelegate {
|
|
private let TAG = "BleServicePlugin"
|
|
|
|
// 方法通道
|
|
private var methodChannel: FlutterMethodChannel?
|
|
|
|
// 事件通道
|
|
private var dataEventSink: FlutterEventSink?
|
|
private var statusEventSink: FlutterEventSink?
|
|
|
|
// BLE服务实例
|
|
private let bleService = BleService.shared
|
|
|
|
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
let methodChannel = FlutterMethodChannel(name: "com.yunqiinnovation.ble_service", binaryMessenger: registrar.messenger())
|
|
|
|
// 创建插件实例
|
|
let instance = SwiftBleServicePlugin()
|
|
instance.methodChannel = methodChannel
|
|
|
|
// 设置方法通道处理器
|
|
registrar.addMethodCallDelegate(instance, channel: methodChannel)
|
|
|
|
// 设置事件通道
|
|
instance.setupEventChannels(with: registrar)
|
|
|
|
// 初始化BLE服务
|
|
_ = instance.bleService.initialize()
|
|
|
|
// 添加自身作为BLE回调
|
|
_ = instance.bleService.addDelegate(instance)
|
|
}
|
|
|
|
/// 设置事件通道
|
|
private func setupEventChannels(with registrar: FlutterPluginRegistrar) {
|
|
// 数据接收事件通道
|
|
let dataEventChannel = FlutterEventChannel(name: "com.yunqiinnovation.ble_service/data_events", binaryMessenger: registrar.messenger())
|
|
dataEventChannel.setStreamHandler(StreamHandler { [weak self] sink in
|
|
self?.dataEventSink = sink
|
|
} onCancel: { [weak self] in
|
|
self?.dataEventSink = nil
|
|
})
|
|
|
|
// 状态更新事件通道
|
|
let statusEventChannel = FlutterEventChannel(name: "com.yunqiinnovation.ble_service/status_events", binaryMessenger: registrar.messenger())
|
|
statusEventChannel.setStreamHandler(StreamHandler { [weak self] sink in
|
|
self?.statusEventSink = sink
|
|
} onCancel: { [weak self] in
|
|
self?.statusEventSink = nil
|
|
})
|
|
}
|
|
|
|
/// 发送事件到Flutter
|
|
private func sendEvent(_ eventSink: FlutterEventSink?, _ data: Any) {
|
|
DispatchQueue.main.async {
|
|
eventSink?(data)
|
|
}
|
|
}
|
|
|
|
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
NSLog("Method call: \(call.method)")
|
|
|
|
switch call.method {
|
|
case "isConnected":
|
|
result(bleService.isConnected())
|
|
|
|
case "getBatteryInfo":
|
|
result(bleService.getBatteryInfo())
|
|
|
|
case "getDeviceVersion":
|
|
result(bleService.getDeviceVersion())
|
|
|
|
case "openEncoder":
|
|
result(bleService.openEncoder())
|
|
|
|
case "openDecoder":
|
|
result(bleService.openDecoder())
|
|
|
|
case "closeCodec":
|
|
result(bleService.closeCodec())
|
|
|
|
case "playA2DP":
|
|
result(bleService.playA2DP())
|
|
|
|
case "registerBackgroundScan":
|
|
result(bleService.registerBackgroundScan())
|
|
|
|
case "unregisterBackgroundScan":
|
|
result(bleService.unregisterBackgroundScan())
|
|
|
|
case "startBleService":
|
|
guard let config = call.arguments as? [String: Any] else {
|
|
result(FlutterError(code: "INVALID_ARGUMENTS", message: "配置参数无效", details: nil))
|
|
return
|
|
}
|
|
|
|
// 处理配置参数
|
|
if let address = config["mac"] as? String {
|
|
// 如果提供了设备地址,尝试连接
|
|
bleService.connect(address: address)
|
|
}
|
|
|
|
// 开始扫描,寻找设备
|
|
let scanSuccess = bleService.startScan()
|
|
result(scanSuccess)
|
|
|
|
case "stopBleService":
|
|
// 停止扫描和断开连接
|
|
_ = bleService.stopScan()
|
|
if bleService.isConnected() {
|
|
bleService.disconnect()
|
|
}
|
|
result(true)
|
|
|
|
default:
|
|
result(FlutterMethodNotImplemented)
|
|
}
|
|
}
|
|
|
|
// MARK: - BleDelegate Methods
|
|
|
|
func onScanResult(devices: [[String: Any]]) {
|
|
// 目前Flutter层没有直接使用此事件,可以选择不转发
|
|
}
|
|
|
|
func onConnectionStateChanged(state: Int) {
|
|
// 将连接状态变化通过状态通道发送
|
|
let stateStr: String
|
|
switch state {
|
|
case BleConst.STATE_DISCONNECTED:
|
|
stateStr = "Disconnected"
|
|
case BleConst.STATE_CONNECTING:
|
|
stateStr = "Connecting"
|
|
case BleConst.STATE_CONNECTED:
|
|
stateStr = "Connected"
|
|
case BleConst.STATE_DISCONNECTING:
|
|
stateStr = "Disconnecting"
|
|
case BleConst.STATE_ERROR:
|
|
stateStr = "Connection Error"
|
|
default:
|
|
stateStr = "Unknown State(\(state))"
|
|
}
|
|
|
|
let stateMap: [String: Any] = [
|
|
"type": "connectionStateChanged",
|
|
"state": state,
|
|
"stateStr": stateStr
|
|
]
|
|
|
|
sendEvent(statusEventSink, stateMap)
|
|
}
|
|
|
|
func onAudioDataReceived(data: Data) {
|
|
// 将音频数据通过数据通道发送
|
|
let dataMap: [String: Any] = [
|
|
"type": "audioData",
|
|
"data": FlutterStandardTypedData(bytes: data)
|
|
]
|
|
|
|
sendEvent(dataEventSink, dataMap)
|
|
}
|
|
|
|
func onWakeupSignalReceived() {
|
|
// 将唤醒事件通过状态通道发送
|
|
sendEvent(statusEventSink, ["type": "wakeup"])
|
|
}
|
|
|
|
func onDeviceInfoReceived(infoType: Int, infoData: [String: Any]) {
|
|
// 将设备信息通过状态通道发送
|
|
var resultMap = infoData
|
|
resultMap["type"] = "deviceInfo"
|
|
resultMap["result"] = infoType
|
|
|
|
sendEvent(statusEventSink, resultMap)
|
|
}
|
|
}
|
|
|
|
// MARK: - 事件处理器类
|
|
|
|
/// 简化的事件处理器类
|
|
class StreamHandler: NSObject, FlutterStreamHandler {
|
|
private let onListen: (FlutterEventSink) -> Void
|
|
private let onCancel: () -> Void
|
|
|
|
init(onListen: @escaping (FlutterEventSink) -> Void, onCancel: @escaping () -> Void) {
|
|
self.onListen = onListen
|
|
self.onCancel = onCancel
|
|
super.init()
|
|
}
|
|
|
|
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
|
|
onListen(events)
|
|
return nil
|
|
}
|
|
|
|
func onCancel(withArguments arguments: Any?) -> FlutterError? {
|
|
onCancel()
|
|
return nil
|
|
}
|
|
}
|