Browse Source

Merge commit '1503669ac75c64450f966dbbdff3f8410be87ea5' into new_dev

newdev_shunjiawei
lxm 1 year ago
parent
commit
1f5bd3a9bc
  1. 12
      lib/data/services/ble_manager.dart
  2. 1
      lib/data/services/bluetooth_manager.dart
  3. 39
      lib/modules/devices/controllers/devices_controller.dart
  4. 84
      lib/modules/devices/views/devices_view.dart
  5. 2
      lib/modules/home/controllers/home_controller.dart
  6. 8
      lib/modules/pairing/controllers/pairing_controller.dart
  7. 17
      local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/SimpleAudioReceiver.kt
  8. 10
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleConst.kt
  9. 63
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt
  10. 10
      local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift
  11. 2
      local_plugins/classic_bluetooth/android/build.gradle.kts
  12. 24
      local_plugins/classic_bluetooth/android/src/main/kotlin/com/yunqiinnovation/classic_bluetooth/ClassicBluetoothPlugin.kt
  13. 8
      local_plugins/classic_bluetooth/ios/classic_bluetooth/Package.swift
  14. 34
      local_plugins/classic_bluetooth/ios/classic_bluetooth/Sources/classic_bluetooth/ClassicBluetoothHelper.swift
  15. 194
      local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt

12
lib/data/services/ble_manager.dart

@ -113,7 +113,7 @@ class BleManager extends GetxService {
// 经典蓝牙实例
// 当前连接的设备信息
String? _currentDeviceAddress;
String? currentDeviceAddress;
String? _currentDeviceName;
// BLE连接状态
@ -513,7 +513,7 @@ class BleManager extends GetxService {
(firmwareVersion != null || batteryLevel != null)) {
Logger.info('lxm--设备信息不存在,创建新的设备信息对象');
// 使用保存的设备信息创建新的DeviceInfo对象
String deviceAddress = _currentDeviceAddress ?? "";
String deviceAddress = currentDeviceAddress ?? "";
String deviceName = _currentDeviceName ?? "";
Logger.info('lxm--创建新的设备信息对象: address=$deviceAddress, name=$deviceName');
@ -561,7 +561,7 @@ class BleManager extends GetxService {
void clearDeviceInfo() {
Logger.info('清除设备信息');
deviceInfo.value = null;
_currentDeviceAddress = null;
currentDeviceAddress = null;
_currentDeviceName = null;
}
@ -573,7 +573,7 @@ class BleManager extends GetxService {
// 确保设备信息对象存在
if (deviceInfo.value == null && _isConnected.value) {
// 创建初始设备信息对象
String deviceAddress = _currentDeviceAddress ?? "";
String deviceAddress = currentDeviceAddress ?? "";
String deviceName = _currentDeviceName ?? "";
Logger.info('初始化设备信息对象: address=$deviceAddress, name=$deviceName');
@ -1036,12 +1036,12 @@ class BleManager extends GetxService {
try {
// 保存设备地址信息
if (macAddress != null) {
_currentDeviceAddress = macAddress;
currentDeviceAddress = macAddress;
// 从蓝牙管理器获取设备名称
final bluetoothManager = Get.find<BluetoothManager>();
_currentDeviceName = bluetoothManager.currentDevice?.name ?? "";
Logger.info(
'保存设备信息: address=$_currentDeviceAddress, name=$_currentDeviceName');
'保存设备信息: address=$currentDeviceAddress, name=$_currentDeviceName');
}
return await _bleService.registerBackgroundScan(macAddress: macAddress);

1
lib/data/services/bluetooth_manager.dart

@ -46,6 +46,7 @@ class BluetoothManager extends GetxService {
/// 释放资源
@override
void onClose() {
print("蓝牙服务关闭");
_bluetoothSubscription?.cancel();
super.onClose();
}

39
lib/modules/devices/controllers/devices_controller.dart

@ -24,29 +24,36 @@ class DevicesController extends GetxController {
@override
void onInit() {
super.onInit();
print("初始化设备管理1");
_bleManager = Get.find<BleManager>();
print("初始化设备管理2");
// 在初始化时加载设备数据
_loadDevices();
}
// 加载设备数据
void _loadDevices() async {
devices.clear();
Logger.info("加载设备");
final response = await Api.getdevices();
if (response != null) {
var devices = (response['devices'] as List<dynamic>)
.map((e) => UserDevice.fromJson(e as Map<String, dynamic>))
.toList();
User.instance.devices = devices;
if (response['devices'] != null) {
var devices = (response['devices'] as List<dynamic>)
.map((e) => UserDevice.fromJson(e as Map<String, dynamic>))
.toList();
User.instance.devices = devices;
} else {
User.instance.devices = [];
}
Logger.info("加载设备 ${User.instance.devices.length}");
}
devices.clear();
for (var device in User.instance.devices) {
if (!devices.containsKey(device.devicetype)) {
devices[device.devicetype] = [];
}
devices[device.devicetype]!.add(device);
}
devices.refresh();
}
@override
@ -59,12 +66,22 @@ class DevicesController extends GetxController {
final response = await Api.unbinddevice({
"id": device.id,
});
Logger.info("解绑设备 $response");
if (response != null) {
// 响应式更新
devices[device.devicetype]?.remove(device);
devices.refresh(); // 触发UI更新
if (device.devicemac == _bleManager.deviceInfo.value?.address) {
User.instance.devices.remove(device);
devices.clear();
for (var device in User.instance.devices) {
if (!devices.containsKey(device.devicetype)) {
devices[device.devicetype] = [];
}
devices[device.devicetype]!.add(device);
}
devices.refresh();
Logger.info(
"解绑设备 ${device.devicemac} 当前使用设备:${_bleManager.currentDeviceAddress}");
if (device.devicemac == _bleManager.currentDeviceAddress) {
Logger.info("解绑设备 $device 重新匹配!");
User.instance.removeUserDevice(device.id);
_bleManager.clearPairedDevices();
_bleManager.disconnect();

84
lib/modules/devices/views/devices_view.dart

@ -118,57 +118,51 @@ class DevicesView extends GetView<DevicesController> {
}
Widget _buildDevicesList(bool isDarkMode) {
final devices = User.instance.devices;
return Obx(() {
// 使用控制器的响应式数据,这会触发控制器的实例化
final groupedDevices = controller.devices;
if (devices.isEmpty) {
return _buildEmptyState(isDarkMode);
}
// 按设备类型分组
final Map<DeviceType, List<UserDevice>> groupedDevices = {};
for (var device in devices) {
final deviceType = DeviceType.fromValue(device.devicetype);
if (!groupedDevices.containsKey(deviceType)) {
groupedDevices[deviceType] = [];
if (groupedDevices.isEmpty) {
return _buildEmptyState(isDarkMode);
}
groupedDevices[deviceType]!.add(device);
}
return ListView(
padding: EdgeInsets.all(20.w),
children: [
// 遍历每个设备类型
...groupedDevices.entries.map((entry) {
final deviceType = entry.key;
final deviceList = entry.value;
return ListView(
padding: EdgeInsets.all(20.w),
children: [
// 遍历每个设备类型
...groupedDevices.entries.map((entry) {
final deviceTypeValue = entry.key;
final deviceList = entry.value;
final deviceType = DeviceType.fromValue(deviceTypeValue);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 设备类型标题
Padding(
padding: EdgeInsets.only(bottom: 12.h),
child: Text(
deviceType.displayName,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87,
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 设备类型标题
Padding(
padding: EdgeInsets.only(bottom: 12.h),
child: Text(
deviceType.displayName,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
),
),
// 该类型下的设备列表
...deviceList.map((device) => _buildDeviceCard(
device: device,
deviceType: deviceType,
isDarkMode: isDarkMode,
)),
SizedBox(height: 20.h),
],
);
}).toList(),
],
);
// 该类型下的设备列表
...deviceList.map((device) => _buildDeviceCard(
device: device,
deviceType: deviceType,
isDarkMode: isDarkMode,
)),
SizedBox(height: 20.h),
],
);
}).toList(),
],
);
});
}
Widget _buildEmptyState(bool isDarkMode) {

2
lib/modules/home/controllers/home_controller.dart

@ -171,7 +171,7 @@ class HomeController extends GetxController {
Future<void> _checkConnectionStatus() async {
try {
final currentBleState = await _bleManager.getConnectionState();
print('fdp--_checkConnectionStatus--currentBleState: $currentBleState');
bool hasClassicBluetooth = currentDevice != null;
bool hasBleConnection = currentBleState == 2;
bool wasConnected = _isFullyConnected.value;

8
lib/modules/pairing/controllers/pairing_controller.dart

@ -922,6 +922,7 @@ class PairingController extends GetxController with WidgetsBindingObserver {
}
List<int> macBytes = [];
List<int> tempBytes = [];
if (Platform.isIOS) {
for (int i = 7; i <= 12; i++) {
// 每个字节异或0x5A
@ -930,6 +931,7 @@ class PairingController extends GetxController with WidgetsBindingObserver {
}
} else if (Platform.isAndroid) {
for (int i = 9; i <= 14; i++) {
tempBytes.add(bytes[i]);
// 每个字节异或0x5A
int decodedByte = bytes[i] ^ 0x5A;
macBytes.add(decodedByte);
@ -940,13 +942,15 @@ class PairingController extends GetxController with WidgetsBindingObserver {
String extractedMac = macBytes
.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase())
.join(':');
String tempMac = tempBytes
.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase())
.join(':');
// 格式化当前设备MAC地址(确保格式一致)
String formattedDeviceMac = deviceMac.replaceAll(':', '').toUpperCase();
String formattedExtractedMac =
extractedMac.replaceAll(':', '').toUpperCase();
print('设备MAC: $deviceMac, 提取的MAC: $extractedMac');
print('设备MAC: $deviceMac, 提取的MAC: $extractedMac tempMac: $tempMac');
// 对比MAC地址
if (formattedDeviceMac == formattedExtractedMac) {

17
local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/tools/SimpleAudioReceiver.kt

@ -237,8 +237,21 @@ fun startAudioRecord(audioSourceType: AudioSourceType, callback: AudioDataCallba
// 设置通话模式 - 这是关键!
audioManager?.mode = AudioManager.MODE_IN_COMMUNICATION
// 启用扬声器(如果需要外放)
audioManager?.isSpeakerphoneOn = true
// 检查是否有蓝牙音频设备连接
val isBluetoothConnected = audioManager?.isBluetoothA2dpOn == true
// 只有在没有蓝牙设备连接时才启用扬声器
if (!isBluetoothConnected) {
audioManager?.isSpeakerphoneOn = true
Log.d("AudioMode", "未检测到蓝牙设备,启用扬声器")
} else {
audioManager?.isSpeakerphoneOn = false
// 启用蓝牙SCO连接
audioManager?.isBluetoothScoOn = true
audioManager?.startBluetoothSco()
Log.d("AudioMode", "检测到蓝牙设备,使用蓝牙音频")
}
// 请求音频焦点
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {

10
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleConst.kt

@ -39,11 +39,11 @@ object BleConst {
const val FOREGROUND_ID = 0xBEE
// ================== 连接状态 ==================
const val STATE_DISCONNECTED = 0
const val STATE_CONNECTING = 1
const val STATE_CONNECTED = 2
const val STATE_DISCONNECTING = 3
const val STATE_ERROR = 4
const val STATE_DISCONNECTED = 0//未连接
const val STATE_CONNECTING = 1//已断开连接
const val STATE_CONNECTED = 2//已连接
const val STATE_DISCONNECTING = 3//连接中
const val STATE_ERROR = 4//连接错误
// ================== 广播厂商信息 ==================
/** 厂商ID - 文档中定义为0xABEF */

63
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

@ -346,7 +346,7 @@ object BleService {
}
val filter = ScanFilter.Builder()
//.setServiceUuid(ParcelUuid(uuid))
.setServiceUuid(ParcelUuid(uuid))
.build()
filters.add(filter)
Log.d(TAG, "添加扫描过滤器UUID: $uuid")
@ -475,16 +475,7 @@ object BleService {
ret.add(info)
}
}
} else {
// 如果没找到匹配设备名的结果,返回所有扫描到的设备信息
for (result in scanResults) {
val info = printDeviceInfo(result)
if (info != null) {
ret.add(info)
}
}
}
return ret
}
@ -595,6 +586,7 @@ object BleService {
* 断开当前连接
*/
fun disconnect() {
Log.d(TAG, "主动断开当前连接")
bluetoothGatt?.disconnect()
updateConnectionState(BleConst.STATE_DISCONNECTING)
}
@ -625,6 +617,7 @@ object BleService {
* 更新连接状态并通知回调
*/
private fun updateConnectionState(state: Int) {
Log.d(TAG, "fdp--------- 更新连接状态: $state")
connectionState.postValue(state)
notifyConnectionStateChanged(state)
}
@ -657,17 +650,24 @@ object BleService {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
// 首先尝试读取当前PHY状态
g.readPhy()
val readResult = g.readPhy()
Log.d(TAG, "读取PHY状态请求结果: $readResult")
// 然后请求设置2M PHY
g.setPreferredPhy(
BluetoothDevice.PHY_LE_2M_MASK, // TX PHY: 2M
BluetoothDevice.PHY_LE_2M_MASK, // RX PHY: 2M
BluetoothDevice.PHY_OPTION_NO_PREFERRED
)
Log.d(TAG, "已请求设置PHY为2M")
// 延迟一段时间后再设置PHY,确保readPhy完成
Handler(Looper.getMainLooper()).postDelayed({
try {
val setResult = g.setPreferredPhy(
BluetoothDevice.PHY_LE_2M_MASK, // TX PHY: 2M
BluetoothDevice.PHY_LE_2M_MASK, // RX PHY: 2M
BluetoothDevice.PHY_OPTION_NO_PREFERRED
)
Log.d(TAG, "设置PHY为2M请求结果: $setResult")
} catch (e: Exception) {
Log.w(TAG, "设置PHY失败: ${e.message}")
}
}, 500) // 延迟500ms
} catch (e: Exception) {
Log.w(TAG, "设置PHY失败: ${e.message},将使用默认1M PHY")
Log.w(TAG, "读取PHY失败: ${e.message},将使用默认1M PHY")
}
} else {
Log.w(TAG, "当前Android版本不支持PHY设置(需要API 26+),使用默认1M PHY")
@ -678,11 +678,13 @@ object BleService {
newState == BluetoothProfile.STATE_DISCONNECTED -> {
updateConnectionState(BleConst.STATE_DISCONNECTED)
Log.d(TAG, "监听到已断开连接")
disconnectGatt()
}
else -> {
updateConnectionState(BleConst.STATE_ERROR)
Log.d(TAG, "监听到连接错误")
disconnectGatt()
}
}
@ -708,6 +710,7 @@ object BleService {
*/
override fun onPhyUpdate(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d(TAG, "PHY更新回调: status=$status, txPhy=$txPhy, rxPhy=$rxPhy")
when (status) {
BluetoothGatt.GATT_SUCCESS -> {
val txPhyStr = getPhyString(txPhy)
@ -721,7 +724,7 @@ object BleService {
Log.w(TAG, "PHY更新出现一般性错误,可能是设备兼容性问题")
}
else -> {
Log.w(TAG, "PHY更新失败: status=$status")
Log.w(TAG, "PHY更新失败: status=$status,设备可能不支持2M PHY")
}
}
}
@ -1506,39 +1509,39 @@ startBytesStatistics()
failureReason.append(" - 原因: BluetoothGatt为空")
} else {
// 检查连接状态
val connectionState = bluetoothManager.getConnectionState(
val State = bluetoothManager.getConnectionState(
bluetoothGatt!!.device,
BluetoothProfile.GATT
)
when (connectionState) {
when (State) {
BluetoothProfile.STATE_DISCONNECTED -> {
failureReason.append(" - 原因: 设备已断开连接")
failureReason.append(" -发送失败 原因: 设备已断开连接")
}
BluetoothProfile.STATE_CONNECTING -> {
failureReason.append(" - 原因: 设备正在连接中")
failureReason.append(" -发送失败 原因: 设备正在连接中")
}
BluetoothProfile.STATE_DISCONNECTING -> {
failureReason.append(" - 原因: 设备正在断开连接")
failureReason.append(" -发送失败 原因: 设备正在断开连接")
}
BluetoothProfile.STATE_CONNECTED -> {
// 连接正常,检查其他原因
if (callWriteChar == null) {
failureReason.append(" - 原因: 写入特征值为空")
failureReason.append(" -发送失败 原因: 写入特征值为空")
} else {
// 检查特征值属性
val properties = callWriteChar!!.properties
if ((properties and BluetoothGattCharacteristic.PROPERTY_WRITE) == 0 &&
(properties and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) {
failureReason.append(" - 原因: 特征值不支持写入操作")
failureReason.append(" -发送失败 原因: 特征值不支持写入操作")
} else if (chunk.size > 512) { // BLE MTU通常限制
failureReason.append(" - 原因: 数据块过大 (${chunk.size} > 512字节)")
failureReason.append(" -发送失败 原因: 数据块过大 (${chunk.size} > 512字节)")
} else {
failureReason.append(" - 原因: 未知错误,可能是设备忙碌或缓冲区满")
failureReason.append(" -发送失败 原因: 未知错误,可能是设备忙碌或缓冲区满")
}
}
}
else -> {
failureReason.append(" - 原因: 未知连接状态($connectionState)")
failureReason.append(" -发送失败 原因: 未知连接状态($connectionState)")
}
}
}

10
local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift

@ -300,13 +300,13 @@ private var cmdReplyType: UInt8 = 0
}
}
// // 开始扫描,使用构建的服务UUID数组进行过滤
// manager.scanForPeripherals(withServices: serviceUUIDs.isEmpty ? nil : serviceUUIDs, options: [
// CBCentralManagerScanOptionAllowDuplicatesKey: true // 允许重复以获取更新的广播数据
// ])
manager.scanForPeripherals(withServices: nil , options: [
// 开始扫描,使用构建的服务UUID数组进行过滤
manager.scanForPeripherals(withServices: serviceUUIDs.isEmpty ? nil : serviceUUIDs, options: [
CBCentralManagerScanOptionAllowDuplicatesKey: true // 允许重复以获取更新的广播数据
])
// manager.scanForPeripherals(withServices: nil , options: [
// CBCentralManagerScanOptionAllowDuplicatesKey: true // 允许重复以获取更新的广播数据
// ])
let filterInfo = serviceUUIDs.isEmpty ? "无过滤" : "过滤器数量: \(serviceUUIDs.count)"
os_log("🔍 开始扫描BLE设备(%{public}@),超时时间: %.1f秒", log: logger, type: .info, filterInfo, timeout)

2
local_plugins/classic_bluetooth/android/build.gradle.kts

@ -34,4 +34,6 @@ android {
dependencies {
add("implementation", "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10")
// 添加对 ble_service 模块的依赖
add("compileOnly", project(":ble_service"))
}

24
local_plugins/classic_bluetooth/android/src/main/kotlin/com/yunqiinnovation/classic_bluetooth/ClassicBluetoothPlugin.kt

@ -15,6 +15,8 @@ import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
// 添加BLE服务导入
import com.yunqiinnovation.ble_service.BleService
/** ClassicBluetoothPlugin */
class ClassicBluetoothPlugin: FlutterPlugin, MethodCallHandler {
@ -135,7 +137,15 @@ class ClassicBluetoothPlugin: FlutterPlugin, MethodCallHandler {
ClassicBluetoothHelper.BluetoothState.TURNING_OFF -> "turningOff"
ClassicBluetoothHelper.BluetoothState.UNKNOWN -> "unknown"
}
if(state == ClassicBluetoothHelper.BluetoothState.OFF){
try {
BleService.disconnect()
Log.d(TAG, "经典蓝牙设备断开,已触发BLE强制断开连接")
} catch (e: Exception) {
Log.e(TAG, "调用BLE强制断开连接失败: ${e.message}", e)
}
}
// 发送状态变化事件
val eventMap = mapOf(
"type" to "stateChanged",
@ -156,11 +166,19 @@ class ClassicBluetoothPlugin: FlutterPlugin, MethodCallHandler {
),
"timestamp" to System.currentTimeMillis()
)
Log.d(TAG, "经典蓝牙设备连接")
sendEvent(eventMap)
}
override fun onDeviceDisconnected(device: Map<String, String>) {
// 经典蓝牙设备断开时,同时断开BLE连接
try {
BleService.disconnect()
Log.d(TAG, "经典蓝牙设备断开,已触发BLE强制断开连接")
} catch (e: Exception) {
Log.e(TAG, "调用BLE强制断开连接失败: ${e.message}", e)
}
// 发送设备断开事件
val eventMap = mapOf(
"type" to "deviceDisconnected",
@ -190,4 +208,4 @@ class ClassicBluetoothPlugin: FlutterPlugin, MethodCallHandler {
Log.e(TAG, "事件发送失败", e)
}
}
}
}

8
local_plugins/classic_bluetooth/ios/classic_bluetooth/Package.swift

@ -11,12 +11,16 @@ let package = Package(
)
],
dependencies: [
// 如果需要其他依赖,在这里添加
// 添加对ble_service的依赖
.package(path: "../../../ble_service/ios/ble_service")
],
targets: [
.target(
name: "classic_bluetooth",
dependencies: [],
dependencies: [
// 添加ble_service产品依赖
.product(name: "ble-service", package: "ble_service")
],
path: "Sources"
)
]

34
local_plugins/classic_bluetooth/ios/classic_bluetooth/Sources/classic_bluetooth/ClassicBluetoothHelper.swift

@ -1,7 +1,7 @@
import Foundation
import AVFoundation
import CoreBluetooth
import ble_service
/// 蓝牙事件类型
public enum BluetoothEventType {
case stateChanged
@ -65,16 +65,35 @@ public class ClassicBluetoothHelper: NSObject, CBCentralManagerDelegate {
case .stateChanged:
if let state = data["state"] as? String {
print("蓝牙状态变化: \(state)")
// configureAudioRouteBasedOnBluetoothState()
}
case .deviceConnected:
print("蓝牙设备已连接")
// 蓝牙设备连接时:末端在手机,输出端在耳机
// configureAudioForBluetoothConnected()
case .deviceDisconnected:
print("蓝牙设备已断开")
// 蓝牙设备断开时:末端和输出端都在手机
/*configureAudioForBluetoothDisconnected*/()
// 蓝牙设备断开时:调用BLE断开连接
disconnectBleOnClassicBluetoothDisconnected()
}
}
/**
* 经典蓝牙断开时调用BLE断开连接
* 当检测到经典蓝牙设备断开时,主动断开BLE连接
*/
private func disconnectBleOnClassicBluetoothDisconnected() {
// 检查BLE服务是否可用
if #available(iOS 13.0, *) {
let bleService = BleService.shared
// 检查BLE是否已连接
if bleService.isConnected() {
print("检测到经典蓝牙断开,正在断开BLE连接...")
bleService.disconnect()
print("BLE连接已断开")
} else {
print("BLE未连接,无需断开")
}
} else {
print("iOS版本不支持BLE服务")
}
}
@ -290,6 +309,9 @@ public class ClassicBluetoothHelper: NSObject, CBCentralManagerDelegate {
"address": cleanDeviceAddress(output.uid)
]
stateCallback?(.deviceDisconnected, ["device": device])
// 在这里调用BLE断开连接
disconnectBleOnClassicBluetoothDisconnected()
}
// 检查当前是否还有蓝牙设备

194
local_plugins/qq_music/android/src/main/kotlin/com/yunqiinnovation/qq_music/QQMusicSingleton.kt

@ -423,52 +423,83 @@ class QQMusicSingleton private constructor() {
action: (QQMusicManager, QQMusicManager.SearchCallback) -> Unit
): (callback: (Result<List<Map<String, Any?>>>) -> Unit) -> Unit {
return lambda@{ callback ->
if (!isQQMusicInstalled()){
callback(Result.failure(Exception("未安装QQ音乐软件,请先安装QQ音乐软件")))
return@lambda
}
val currentActivity = context
if (currentActivity == null) {
callback(Result.failure(Exception("Activity not available")))
return@lambda
}
Log.d(TAG, "开始 ${actionName}")
ensureMusicManager(currentActivity,object: QQMusicManager. BindCallback{
override fun onSuccess(){
action(musicManager!!, object : QQMusicManager.SearchCallback {
override fun onSuccess(songs: List<Map<String, Any?>>) {
Log.d(TAG, "${actionName} 成功")
handler.post {
callback(Result.success(songs))
}
}
override fun onError(errorCode: Int, errorMessage: String) {
Log.d(TAG, "失败 ${actionName} 成功")
if (allagain > 0 && curragain < allagain){ //重试机制
executeSearchbackAction(actionName,curragain+1,allagain,action)
}else{
handler.post {
callback(Result.failure(Exception("$actionName 失败: $errorMessage")))
}
}
}
})
// 添加登录状态检查
if (!isLoggedIn()) {
Log.d(TAG, "用户未登录,开始自动登录")
login { loginResult ->
if (loginResult.isSuccess) {
Log.d(TAG, "自动登录成功,继续执行 ${actionName}")
// 登录成功后继续执行原操作
executeSearchAction(actionName, curragain, allagain, action, callback)
} else {
Log.e(TAG, "自动登录失败: ${loginResult.exceptionOrNull()?.message}")
callback(Result.failure(Exception("用户未登录且自动登录失败: ${loginResult.exceptionOrNull()?.message}")))
}
}
override fun onError(errorCode: Int, errorMessage: String) {
if (allagain > 0 && curragain < allagain){ //重试机制
executeSearchbackAction(actionName,curragain+1,allagain,action)
}else{
return@lambda
}
// 用户已登录,直接执行搜索操作
executeSearchAction(actionName, curragain, allagain, action, callback)
}
}
// 提取搜索执行逻辑为独立方法
private fun executeSearchAction(
actionName: String,
curragain: Int,
allagain: Int,
action: (QQMusicManager, QQMusicManager.SearchCallback) -> Unit,
callback: (Result<List<Map<String, Any?>>>) -> Unit
) {
Log.d(TAG, "开始 ${actionName}")
ensureMusicManager(context!!, object: QQMusicManager.BindCallback{
override fun onSuccess(){
action(musicManager!!, object : QQMusicManager.SearchCallback {
override fun onSuccess(songs: List<Map<String, Any?>>) {
Log.d(TAG, "${actionName} 成功")
handler.post {
callback(Result.failure(Exception("$actionName 失败: $errorMessage")))
callback(Result.success(songs))
}
}
override fun onError(errorCode: Int, errorMessage: String) {
Log.d(TAG, "失败 ${actionName} errorCode: $errorCode errorMessage:$errorMessage 当前重试${curragain}/${allagain}")
if (allagain > 0 && curragain < allagain){ //重试机制
Log.d(TAG, "重试 ${actionName} 当前重试${curragain+1}/${allagain}")
executeSearchbackAction(actionName,curragain+1,allagain,action)(callback)
}else{
handler.post {
callback(Result.failure(Exception("$actionName 失败: $errorMessage")))
}
}
}
})
}
override fun onError(errorCode: Int, errorMessage: String) {
Log.d(TAG, "失败 ${actionName} errorCode: $errorCode errorMessage:$errorMessage 当前重试${curragain}/${allagain}")
if (allagain > 0 && curragain < allagain){ //重试机制
Log.d(TAG, "重试 ${actionName} 当前重试${curragain+1}/${allagain}")
executeSearchbackAction(actionName,curragain+1,allagain,action)(callback)
}else{
handler.post {
callback(Result.failure(Exception("$actionName 失败: $errorMessage")))
}
}
})
}
}
})
}
@ -491,49 +522,80 @@ class QQMusicSingleton private constructor() {
callback(Result.failure(Exception("Activity not available")))
return@lambda
}
Log.d(TAG, "开始 ${actionName}")
ensureMusicManager(currentActivity,object: QQMusicManager. BindCallback{
override fun onSuccess(){
action(musicManager!!, object : QQMusicManager.PlayCallback {
override fun onSuccess() {
Log.d(TAG, "${actionName}成功")
handler.post {
callback(Result.success(Unit))
}
// 添加登录状态检查
if (!isLoggedIn()) {
Log.d(TAG, "用户未登录,开始自动登录")
login { loginResult ->
if (loginResult.isSuccess) {
Log.d(TAG, "自动登录成功,继续执行 ${actionName}")
// 登录成功后继续执行原操作
executePlayAction(actionName, curragain, allagain, action, callback)
} else {
Log.e(TAG, "自动登录失败: ${loginResult.exceptionOrNull()?.message}")
callback(Result.failure(Exception("用户未登录且自动登录失败: ${loginResult.exceptionOrNull()?.message}")))
}
}
return@lambda
}
// 用户已登录,直接执行搜索操作
executePlayAction(actionName, curragain, allagain, action, callback)
}
}
private fun executePlayAction(
actionName: String,
curragain:Int,
allagain:Int,
action: (QQMusicManager, QQMusicManager.PlayCallback) -> Unit,
callback: (Result<Unit>) -> Unit
) {
Log.d(TAG, "开始 ${actionName}")
ensureMusicManager(context!!,object: QQMusicManager. BindCallback{
override fun onSuccess(){
action(musicManager!!, object : QQMusicManager.PlayCallback {
override fun onSuccess() {
Log.d(TAG, "${actionName}成功")
handler.post {
callback(Result.success(Unit))
}
}
override fun onError(errorCode: Int, errorMessage: String) {
if (allagain > 0 && curragain < allagain){ //重试机制
executePlaybackAction(actionName,curragain+1,allagain,action)
}else{
handler.post {
Log.e(TAG, "${actionName}失败: $errorCode $errorMessage")
if (errorCode == -1){
musicManager?.bindQQMusicApiService()
callback(Result.failure(Exception("播放失败: $errorMessage")))
} else if (errorCode == 1030) {
callback(Result.success(Unit))
}else{
callback(Result.failure(Exception("播放失败: $errorMessage")))
}
override fun onError(errorCode: Int, errorMessage: String) {
if (allagain > 0 && curragain < allagain){ //重试机制
executePlaybackAction(actionName,curragain+1,allagain,action)(callback)
}else{
handler.post {
Log.e(TAG, "${actionName}失败: $errorCode $errorMessage")
if (errorCode == -1){
musicManager?.bindQQMusicApiService()
callback(Result.failure(Exception("播放失败: $errorMessage")))
} else if (errorCode == 1030) {
callback(Result.success(Unit))
}else{
callback(Result.failure(Exception("播放失败: $errorMessage")))
}
}
}
})
}
override fun onError(errorCode: Int, errorMessage: String) {
Log.e(TAG, "${actionName}失败: $errorCode $errorMessage")
if (allagain > 0 && curragain < allagain){ //重试机制
executePlaybackAction(actionName,curragain+1,allagain,action)
}else{
callback(Result.failure(Exception("$actionName 失败: $errorMessage")))
}
})
}
override fun onError(errorCode: Int, errorMessage: String) {
Log.e(TAG, "${actionName}失败: $errorCode $errorMessage")
if (allagain > 0 && curragain < allagain){ //重试机制
executePlaybackAction(actionName,curragain+1,allagain,action)(callback)
}else{
callback(Result.failure(Exception("$actionName 失败: $errorMessage")))
}
})
}
})
}
}
private fun executeInfoAction(
actionName: String,
action: (QQMusicManager, QQMusicManager.InfoCallback) -> Unit

Loading…
Cancel
Save