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.

513 lines
14 KiB

import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/services.dart';
/// BLE连接状态常量
class BleConnectionState {
static const int disconnected = 0;
static const int connecting = 1;
static const int connected = 2;
static const int disconnecting = 3;
static const int error = 4;
}
/// BLE服务插件
class BleService {
static final BleService _instance = BleService._internal();
/// 获取单例
factory BleService() => _instance;
// 方法通道
final MethodChannel _methodChannel =
const MethodChannel('com.yunqiinnovation.ble_service');
// 事件通道 - 简化为只使用数据和状态通道
late final EventChannel _dataEventChannel;
late final EventChannel _statusEventChannel;
// 事件流
late final Stream<dynamic> _dataStream;
late final Stream<dynamic> _statusStream;
// 获取事件流
Stream<dynamic> get onDataReceived => _dataStream;
// 状态流直接传递原始数据
Stream<dynamic> get onStatusUpdated => _statusStream;
// 内部构造函数
BleService._internal() {
_dataEventChannel =
const EventChannel('com.yunqiinnovation.ble_service/data_events');
_statusEventChannel =
const EventChannel('com.yunqiinnovation.ble_service/status_events');
// 初始化事件流
_dataStream = _dataEventChannel.receiveBroadcastStream();
_statusStream = _statusEventChannel.receiveBroadcastStream();
}
/// 检查是否已连接
Future<bool> isConnected() async {
try {
final result = await _methodChannel.invokeMethod<bool>('isConnected');
return result ?? false;
} catch (e) {
print('检查连接状态失败: $e');
return false;
}
}
/// 获取电池电量
Future<int> getBatteryLevel() async {
try {
final result = await _methodChannel.invokeMethod<int>('getBatteryLevel');
return result ?? 0;
} catch (e) {
print('获取电池电量失败: $e');
return 0;
}
}
/// 获取设备版本信息
Future<bool> getDeviceVersion() async {
try {
final result =
await _methodChannel.invokeMethod<bool>('getDeviceVersion');
return result ?? false;
} catch (e) {
print('获取设备版本失败: $e');
return false;
}
}
/// 获取产品ID
Future<bool> getProductId() async {
try {
final result = await _methodChannel.invokeMethod<bool>('getProductId');
return result ?? false;
} catch (e) {
print('获取设备版本失败: $e');
return false;
}
}
/// 获取电池信息
Future<bool> getBatteryInfo() async {
try {
final result = await _methodChannel.invokeMethod<bool>('getBatteryInfo');
return result ?? false;
} catch (e) {
print('获取电池信息失败: $e');
return false;
}
}
/// 打开编码器
Future<bool> openEncoder() async {
try {
final result = await _methodChannel.invokeMethod<bool>('openEncoder');
return result ?? false;
} catch (e) {
print('打开编码器失败: $e');
return false;
}
}
/// 打开解码器
Future<bool> openDecoder() async {
try {
final result = await _methodChannel.invokeMethod<bool>('openDecoder');
return result ?? false;
} catch (e) {
print('打开解码器失败: $e');
return false;
}
}
/// 打开解码器
Future<bool> openA2DPDecoder() async {
try {
final result = await _methodChannel.invokeMethod<bool>('openA2DPDecoder');
return result ?? false;
} catch (e) {
print('打开解码器失败: $e');
return false;
}
}
/// 打开解码器
Future<bool> openCallRecordDecoder() async {
try {
final result =
await _methodChannel.invokeMethod<bool>('openCallRecordDecoder');
return result ?? false;
} catch (e) {
print('打开解码器失败: $e');
return false;
}
}
/// 关闭编解码器
Future<bool> closeCodec() async {
try {
final result = await _methodChannel.invokeMethod<bool>('closeCodec');
return result ?? false;
} catch (e) {
print('关闭编解码器失败: $e');
return false;
}
}
/// 播放A2DP
Future<bool> playA2DP() async {
try {
final result = await _methodChannel.invokeMethod<bool>('playA2DP');
return result ?? false;
} catch (e) {
print('播放A2DP失败: $e');
return false;
}
}
/// 启动BLE后台服务
Future<bool> startBleService(Map<String, dynamic> config) async {
try {
final result =
await _methodChannel.invokeMethod<bool>('startBleService', config);
return result ?? false;
} catch (e) {
print('启动BLE后台服务失败: $e');
return false;
}
}
/// 停止BLE后台服务
Future<bool> stopBleService() async {
try {
final result = await _methodChannel.invokeMethod<bool>('stopBleService');
return result ?? false;
} catch (e) {
print('停止BLE后台服务失败: $e');
return false;
}
}
//========================================================================
// 以下是Companion Device相关功能
//========================================================================
/// 检查设备是否支持Companion Device Manager
///
/// 返回设备是否支持Companion Device Manager API
/// 仅在Android 8.0及以上版本可用
Future<bool> isCompanionSupported() async {
try {
final result =
await _methodChannel.invokeMethod<bool>('isCompanionSupported');
return result ?? false;
} catch (e) {
print('检查Companion设备支持失败: $e');
return false;
}
}
/// 启动设备关联流程
///
/// 弹出系统设备选择对话框,用户选择后将建立持久化关联
/// 关联成功后,应用将获得后台扫描和启动前台服务的特权
///
/// [deviceNamePattern] 设备名称正则表达式,例如"MyHeadset.*"
/// [serviceUuid] 可选的服务UUID
/// [macAddress] 可选的MAC地址
///
/// 返回是否成功启动关联流程
Future<bool> startDeviceAssociation({
String? deviceNamePattern,
String? serviceUuid,
String? macAddress,
}) async {
try {
final result = await _methodChannel.invokeMethod<bool>(
'startDeviceAssociation',
{
'deviceNamePattern': deviceNamePattern,
'serviceUuid': serviceUuid,
'macAddress': macAddress,
},
);
return result ?? false;
} catch (e) {
print('启动设备关联失败: $e');
return false;
}
}
/// 获取已关联的设备MAC地址
///
/// 返回已关联的设备MAC地址,如果没有则返回null
Future<String?> getPairedMacAddress() async {
try {
final result =
await _methodChannel.invokeMethod<String>('getPairedMacAddress');
return result;
} catch (e) {
print('获取配对MAC地址失败: $e');
return null;
}
}
/// 检查BLE连接状态
///
/// 返回BLE是否已连接
Future<bool> isBleConnected() async {
try {
final result = await _methodChannel.invokeMethod<bool>('isBleConnected');
return result ?? false;
} catch (e) {
print('检查BLE连接状态失败: $e');
return false;
}
}
/// 设置是否是ota模式
Future<void> setEnterOta(bool enterOta) async {
try {
await _methodChannel.invokeMethod<String>('setEnterOta', {
'enterOta': enterOta,
});
} catch (e) {
print('设置是否是ota模式失败: $e');
}
}
/// 设置是否是否需要唤醒
Future<void> setWakeup(bool wakeup) async {
try {
await _methodChannel.invokeMethod<String>('setWakeup', {
'wakeup': wakeup,
});
} catch (e) {
print('设置是否是否需要唤醒失败: $e');
}
}
/// 断开连接
Future<void> disconnect() async {
try {
await _methodChannel.invokeMethod<String>('disconnect');
} catch (e) {
print('断开连接失败: $e');
}
}
/// 断开连接
Future<bool> startScan(List<String> uuids) async {
try {
final result = await _methodChannel
.invokeMethod<bool>('startScan', {'uuids': uuids});
return result ?? false;
} catch (e) {
print('开启扫描ble设备失败: $e');
return false;
}
}
/// 断开连接
Future<bool> stopScan() async {
try {
final result = await _methodChannel.invokeMethod<bool>('stopScan');
return result ?? false;
} catch (e) {
print('开启扫描ble设备失败: $e');
return false;
}
}
/// 获取设备信息
Future<Map<String, String>?> getDeviceInfo(String deviceName) async {
try {
final result = await _methodChannel
.invokeMethod<Map>('getDeviceInfo', {'deviceName': deviceName});
print('获取设备信息!: $result');
if (result != null) {
return {
'name': result['name'] ?? "未知",
'address': result['address'] ?? "",
'id': result['id'] ??
result['address'] ??
"", // iOS 返回 UUID,Android 返回 address
'hex': result['hex'] ?? "",
};
} else {
return null;
}
} catch (e) {
print('获取设备信息失败!: $e');
return null;
}
}
/// 获取设备列表(通过设备名)
Future<List<Map<String, String>>?> getDeviceList(String deviceName) async {
try {
final result = await _methodChannel
.invokeMethod<List>('getDeviceList', {'deviceName': deviceName});
print('获取设备列表!: $result');
if (result != null) {
return result.map<Map<String, String>>((device) {
return {
'name': device['name'] ?? "未知",
'address': device['address'] ?? "",
'id': device['id'] ??
device['address'] ??
"", // iOS 返回 UUID,Android 返回 address
'hex': device['hex'] ?? "",
};
}).toList();
} else {
return null;
}
} catch (e) {
print('获取设备列表失败!: $e');
return null;
}
}
/// 注册BLE后台扫描
///
/// 注册后,即使应用被杀死,系统也会在检测到设备广播时唤醒应用
/// 这是确保设备可以在应用后台时被自动连接的关键功能
///
/// [macAddress] 可选的设备MAC地址,如果不提供则使用已关联的设备
Future<bool> registerBackgroundScan({String? macAddress}) async {
try {
final result =
await _methodChannel.invokeMethod<bool>('registerBackgroundScan');
return result ?? false;
} catch (e) {
print('注册后台扫描失败: $e');
return false;
}
}
/// 注销BLE后台扫描
///
/// 当不再需要后台扫描功能时调用,例如用户主动断开连接时
Future<bool> unregisterBackgroundScan() async {
try {
final result =
await _methodChannel.invokeMethod<bool>('unregisterBackgroundScan');
return result ?? false;
} catch (e) {
print('注销后台扫描失败: $e');
return false;
}
}
/// 清除所有设备关联
///
/// 用于重置设备关联状态,通常在用户主动解除关联或调试时使用
Future<bool> clearAssociations() async {
try {
final result =
await _methodChannel.invokeMethod<bool>('clearAssociations');
return result ?? false;
} catch (e) {
print('清除设备关联失败: $e');
return false;
}
}
//========================================================================
// 以下是ChatAgent相关功能
//========================================================================
/// 初始化语音交互代理
///
/// [config] 配置参数,必须包含:
/// - azureSpeechKey: Azure语音服务API密钥
/// - azureSpeechRegion: Azure语音服务区域
/// - openaiApiKey: OpenAI API密钥
/// - openaiBaseUrl: OpenAI API基础URL
/// - openaiModel: OpenAI模型名称,默认为'gpt-3.5-turbo'
Future<bool> initializeChatAgent(Map<String, dynamic> config) async {
try {
final result = await _methodChannel.invokeMethod<bool>(
'initializeChatAgent', config);
return result ?? false;
} catch (e) {
print('初始化语音交互代理失败: $e');
return false;
}
}
/// 启动语音识别
///
/// 用于手动启动语音识别,通常不需要直接调用,因为在唤醒时会自动启动
Future<bool> startListening() async {
try {
final result = await _methodChannel.invokeMethod<bool>('startListening');
return result ?? false;
} catch (e) {
print('启动语音识别失败: $e');
return false;
}
}
/// 停止语音识别
Future<bool> stopListening() async {
try {
final result = await _methodChannel.invokeMethod<bool>('stopListening');
return result ?? false;
} catch (e) {
print('停止语音识别失败: $e');
return false;
}
}
/// 处理文本输入
///
/// [text] 用户输入的文本
/// [speakResponse] 是否使用TTS朗读回复,默认为false
Future<bool> processTextInput(String text,
{bool speakResponse = false}) async {
try {
final result =
await _methodChannel.invokeMethod<bool>('processTextInput', {
'text': text,
'speakResponse': speakResponse,
});
return result ?? false;
} catch (e) {
print('处理文本输入失败: $e');
return false;
}
}
/// 停止TTS播放
Future<bool> stopTts() async {
try {
final result = await _methodChannel.invokeMethod<bool>('stopTts');
return result ?? false;
} catch (e) {
print('停止TTS播放失败: $e');
return false;
}
}
/// 请求蓝牙权限(仅iOS)
Future<bool> requestBluetoothPermission() async {
try {
final result =
await _methodChannel.invokeMethod<bool>('requestBluetoothPermission');
return result ?? false;
} catch (e) {
print('请求蓝牙权限失败: $e');
return false;
}
}
}