|
|
@ -8,7 +8,7 @@ import android.content.Context |
|
|
import android.content.Intent |
|
|
import android.content.Intent |
|
|
import android.os.* |
|
|
import android.os.* |
|
|
import androidx.lifecycle.MutableLiveData |
|
|
import androidx.lifecycle.MutableLiveData |
|
|
import com.yunqiinnovation.deepvoice_utils.FileLogger |
|
|
import android.util.Log |
|
|
import java.io.File |
|
|
import java.io.File |
|
|
import java.io.FileOutputStream |
|
|
import java.io.FileOutputStream |
|
|
import java.text.SimpleDateFormat |
|
|
import java.text.SimpleDateFormat |
|
|
@ -122,8 +122,8 @@ object BleService { |
|
|
setDataCallback(object : OTAManager.DataCallback { |
|
|
setDataCallback(object : OTAManager.DataCallback { |
|
|
override fun onDataReceived(device: BluetoothDevice?, data: ByteArray?) { |
|
|
override fun onDataReceived(device: BluetoothDevice?, data: ByteArray?) { |
|
|
data?.let { |
|
|
data?.let { |
|
|
FileLogger.i("BleService", "收到数据:${it.size} 字节") |
|
|
Log.i("BleService", "收到数据:${it.size} 字节") |
|
|
FileLogger.i("BleService", "认证交互数据${it.contentToString()}") |
|
|
Log.i("BleService", "认证交互数据${it.contentToString()}") |
|
|
// 移除次数限制,除非明确需要 |
|
|
// 移除次数限制,除非明确需要 |
|
|
otaManager?.onReceiveDeviceData(device, it) |
|
|
otaManager?.onReceiveDeviceData(device, it) |
|
|
} |
|
|
} |
|
|
@ -143,19 +143,17 @@ object BleService { |
|
|
try { |
|
|
try { |
|
|
opusManager = OpusManager() |
|
|
opusManager = OpusManager() |
|
|
startOpusStreamDecoding() |
|
|
startOpusStreamDecoding() |
|
|
FileLogger.d(TAG, "OpusManager初始化成功") |
|
|
Log.d(TAG, "OpusManager初始化成功") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (e: OpusException) { |
|
|
} catch (e: OpusException) { |
|
|
FileLogger.e(TAG, "OpusManager初始化失败: ${e.message}", e) |
|
|
Log.e(TAG, "OpusManager初始化失败: ${e.message}", e) |
|
|
// 根据需要决定是否因为Opus初始化失败而返回false |
|
|
// 根据需要决定是否因为Opus初始化失败而返回false |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
isInitialized = true |
|
|
isInitialized = true |
|
|
FileLogger.d(TAG, "BLE服务初始化成功") |
|
|
Log.d(TAG, "BLE服务初始化成功") |
|
|
return true |
|
|
return true |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "BLE服务初始化失败: ${e.message}", e) |
|
|
Log.e(TAG, "BLE服务初始化失败: ${e.message}", e) |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -168,7 +166,7 @@ object BleService { |
|
|
fun addCallback(callback: Callback): Boolean { |
|
|
fun addCallback(callback: Callback): Boolean { |
|
|
if (!callbacks.contains(callback)) { |
|
|
if (!callbacks.contains(callback)) { |
|
|
callbacks.add(callback) |
|
|
callbacks.add(callback) |
|
|
FileLogger.d(TAG, "已添加BLE回调, 当前回调数: ${callbacks.size}") |
|
|
Log.d(TAG, "已添加BLE回调, 当前回调数: ${callbacks.size}") |
|
|
return true |
|
|
return true |
|
|
} |
|
|
} |
|
|
return false |
|
|
return false |
|
|
@ -182,7 +180,7 @@ object BleService { |
|
|
fun removeCallback(callback: Callback): Boolean { |
|
|
fun removeCallback(callback: Callback): Boolean { |
|
|
val removed = callbacks.remove(callback) |
|
|
val removed = callbacks.remove(callback) |
|
|
if (removed) { |
|
|
if (removed) { |
|
|
FileLogger.d(TAG, "已移除BLE回调, 当前回调数: ${callbacks.size}") |
|
|
Log.d(TAG, "已移除BLE回调, 当前回调数: ${callbacks.size}") |
|
|
} |
|
|
} |
|
|
return removed |
|
|
return removed |
|
|
} |
|
|
} |
|
|
@ -192,7 +190,7 @@ object BleService { |
|
|
*/ |
|
|
*/ |
|
|
fun clearCallbacks() { |
|
|
fun clearCallbacks() { |
|
|
callbacks.clear() |
|
|
callbacks.clear() |
|
|
FileLogger.d(TAG, "已清除所有BLE回调") |
|
|
Log.d(TAG, "已清除所有BLE回调") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// ====================================================================================================== |
|
|
// ====================================================================================================== |
|
|
@ -205,7 +203,7 @@ object BleService { |
|
|
*/ |
|
|
*/ |
|
|
fun startScan(timeout: Long = 15000): Boolean { |
|
|
fun startScan(timeout: Long = 15000): Boolean { |
|
|
if (!isInitialized) { |
|
|
if (!isInitialized) { |
|
|
FileLogger.e(TAG, "BLE服务未初始化") |
|
|
Log.e(TAG, "BLE服务未初始化") |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -213,7 +211,7 @@ object BleService { |
|
|
val scanner = bluetoothLeScanner ?: return false |
|
|
val scanner = bluetoothLeScanner ?: return false |
|
|
if (isScanning) return false |
|
|
if (isScanning) return false |
|
|
|
|
|
|
|
|
FileLogger.i(TAG, "开始主动扫描BLE设备...") |
|
|
Log.i(TAG, "开始主动扫描BLE设备...") |
|
|
scanResults.clear() |
|
|
scanResults.clear() |
|
|
|
|
|
|
|
|
val filter = ScanFilter.Builder() |
|
|
val filter = ScanFilter.Builder() |
|
|
@ -234,13 +232,13 @@ object BleService { |
|
|
|
|
|
|
|
|
// 设置扫描超时 |
|
|
// 设置扫描超时 |
|
|
scanHandler.postDelayed({ |
|
|
scanHandler.postDelayed({ |
|
|
FileLogger.d(TAG, "扫描超时,停止扫描") |
|
|
Log.d(TAG, "扫描超时,停止扫描") |
|
|
stopScan() |
|
|
stopScan() |
|
|
}, timeout) |
|
|
}, timeout) |
|
|
|
|
|
|
|
|
return true |
|
|
return true |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "启动扫描失败: ${e.message}", e) |
|
|
Log.e(TAG, "启动扫描失败: ${e.message}", e) |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -254,7 +252,7 @@ object BleService { |
|
|
val scanner = bluetoothLeScanner ?: return false |
|
|
val scanner = bluetoothLeScanner ?: return false |
|
|
if (!isScanning) return false |
|
|
if (!isScanning) return false |
|
|
|
|
|
|
|
|
FileLogger.i(TAG, "停止主动扫描") |
|
|
Log.i(TAG, "停止主动扫描") |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
scanner.stopScan(scanCallback) |
|
|
scanner.stopScan(scanCallback) |
|
|
@ -264,7 +262,7 @@ object BleService { |
|
|
|
|
|
|
|
|
return true |
|
|
return true |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "停止扫描失败: ${e.message}", e) |
|
|
Log.e(TAG, "停止扫描失败: ${e.message}", e) |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -298,12 +296,12 @@ object BleService { |
|
|
val idx = scanResults.indexOfFirst { it.device.address == dev.address } |
|
|
val idx = scanResults.indexOfFirst { it.device.address == dev.address } |
|
|
if (idx >= 0) scanResults[idx] = result else scanResults.add(result) |
|
|
if (idx >= 0) scanResults[idx] = result else scanResults.add(result) |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "上报扫描结果异常: ${e.message}", e) |
|
|
Log.e(TAG, "上报扫描结果异常: ${e.message}", e) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
override fun onScanFailed(errorCode: Int) { |
|
|
override fun onScanFailed(errorCode: Int) { |
|
|
FileLogger.e(TAG, "扫描失败 error=$errorCode") |
|
|
Log.e(TAG, "扫描失败 error=$errorCode") |
|
|
isScanning = false |
|
|
isScanning = false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -317,7 +315,7 @@ object BleService { |
|
|
val serviceUuids = |
|
|
val serviceUuids = |
|
|
scanRecord?.serviceUuids?.joinToString(", ") { it.uuid.toString() } ?: "无" |
|
|
scanRecord?.serviceUuids?.joinToString(", ") { it.uuid.toString() } ?: "无" |
|
|
|
|
|
|
|
|
FileLogger.d( |
|
|
Log.d( |
|
|
TAG, "扫描到设备: 名称=${device.name ?: "未知"}, 地址=${device.address}, " + |
|
|
TAG, "扫描到设备: 名称=${device.name ?: "未知"}, 地址=${device.address}, " + |
|
|
"RSSI=${result.rssi}, 服务UUID=[$serviceUuids]" |
|
|
"RSSI=${result.rssi}, 服务UUID=[$serviceUuids]" |
|
|
) |
|
|
) |
|
|
@ -326,12 +324,12 @@ object BleService { |
|
|
val scanData = scanRecord?.bytes |
|
|
val scanData = scanRecord?.bytes |
|
|
if (scanData != null) { |
|
|
if (scanData != null) { |
|
|
val hexString = scanData.joinToString("") { String.format("%02X", it) } |
|
|
val hexString = scanData.joinToString("") { String.format("%02X", it) } |
|
|
FileLogger.d(TAG, "广播数据: $hexString") |
|
|
Log.d(TAG, "广播数据: $hexString") |
|
|
|
|
|
|
|
|
// 解析服务数据 |
|
|
// 解析服务数据 |
|
|
scanRecord.serviceData?.forEach { (uuid, data) -> |
|
|
scanRecord.serviceData?.forEach { (uuid, data) -> |
|
|
val dataHex = data.joinToString("") { String.format("%02X", it) } |
|
|
val dataHex = data.joinToString("") { String.format("%02X", it) } |
|
|
FileLogger.d(TAG, "服务数据: UUID=${uuid.uuid}, 数据=$dataHex") |
|
|
Log.d(TAG, "服务数据: UUID=${uuid.uuid}, 数据=$dataHex") |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -352,16 +350,16 @@ object BleService { |
|
|
val pairedMac = companionManager.getPairedMacAddress() |
|
|
val pairedMac = companionManager.getPairedMacAddress() |
|
|
|
|
|
|
|
|
if (pairedMac.isNullOrEmpty()) { |
|
|
if (pairedMac.isNullOrEmpty()) { |
|
|
FileLogger.w(TAG, "未找到已配对的设备 MAC 地址") |
|
|
Log.w(TAG, "未找到已配对的设备 MAC 地址") |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
FileLogger.i(TAG, "检测到已配对设备,MAC: $pairedMac,尝试连接") |
|
|
Log.i(TAG, "检测到已配对设备,MAC: $pairedMac,尝试连接") |
|
|
|
|
|
|
|
|
// 调用现有的 connect 方法 |
|
|
// 调用现有的 connect 方法 |
|
|
connect(pairedMac) |
|
|
connect(pairedMac) |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "自动连接已配对设备失败: ${e.message}", e) |
|
|
Log.e(TAG, "自动连接已配对设备失败: ${e.message}", e) |
|
|
updateConnectionState(BleConst.STATE_ERROR) |
|
|
updateConnectionState(BleConst.STATE_ERROR) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -373,7 +371,7 @@ object BleService { |
|
|
*/ |
|
|
*/ |
|
|
fun connect(address: String) { |
|
|
fun connect(address: String) { |
|
|
if (connectionState.value == BleConst.STATE_CONNECTED) { |
|
|
if (connectionState.value == BleConst.STATE_CONNECTED) { |
|
|
FileLogger.w(TAG, "已经连接中,忽略连接请求") |
|
|
Log.w(TAG, "已经连接中,忽略连接请求") |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -399,7 +397,7 @@ object BleService { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "连接设备失败: ${e.message}", e) |
|
|
Log.e(TAG, "连接设备失败: ${e.message}", e) |
|
|
updateConnectionState(BleConst.STATE_ERROR) |
|
|
updateConnectionState(BleConst.STATE_ERROR) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -421,7 +419,7 @@ object BleService { |
|
|
gatt.disconnect() |
|
|
gatt.disconnect() |
|
|
gatt.close() |
|
|
gatt.close() |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "关闭GATT连接异常: ${e.message}", e) |
|
|
Log.e(TAG, "关闭GATT连接异常: ${e.message}", e) |
|
|
} |
|
|
} |
|
|
bluetoothGatt = null |
|
|
bluetoothGatt = null |
|
|
notifyChar = null |
|
|
notifyChar = null |
|
|
@ -433,9 +431,9 @@ object BleService { |
|
|
fun startOTA() { |
|
|
fun startOTA() { |
|
|
try { |
|
|
try { |
|
|
otaManager?.startOTA(CustomUpdateCallback(context, null)) |
|
|
otaManager?.startOTA(CustomUpdateCallback(context, null)) |
|
|
FileLogger.i(TAG, "OTA 升级已启动") |
|
|
Log.i(TAG, "OTA 升级已启动") |
|
|
} catch (e: IllegalStateException) { |
|
|
} catch (e: IllegalStateException) { |
|
|
FileLogger.e(TAG, "OTA 启动失败: ${e.message}") |
|
|
Log.e(TAG, "OTA 启动失败: ${e.message}") |
|
|
disconnectGatt() |
|
|
disconnectGatt() |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -448,7 +446,7 @@ object BleService { |
|
|
val file = File(firmwarePath) |
|
|
val file = File(firmwarePath) |
|
|
if (!file.exists()) { |
|
|
if (!file.exists()) { |
|
|
// throw IOException("Firmware file not found") |
|
|
// throw IOException("Firmware file not found") |
|
|
FileLogger.i(TAG, "Firmware file not found") |
|
|
Log.i(TAG, "Firmware file not found") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val bluetoothOption = BluetoothOTAConfigure().apply { |
|
|
val bluetoothOption = BluetoothOTAConfigure().apply { |
|
|
@ -461,10 +459,10 @@ object BleService { |
|
|
firmwareFilePath = firmwarePath |
|
|
firmwareFilePath = firmwarePath |
|
|
} |
|
|
} |
|
|
otaManager?.configure(bluetoothOption) ?: run { |
|
|
otaManager?.configure(bluetoothOption) ?: run { |
|
|
FileLogger.e(TAG, "OTA Manager未初始化") |
|
|
Log.e(TAG, "OTA Manager未初始化") |
|
|
} |
|
|
} |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "OTA配置失败: ${e.message}") |
|
|
Log.e(TAG, "OTA配置失败: ${e.message}") |
|
|
// 处理错误 |
|
|
// 处理错误 |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -485,12 +483,12 @@ object BleService { |
|
|
|
|
|
|
|
|
override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) { |
|
|
override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) { |
|
|
if (status == BluetoothGatt.GATT_SUCCESS) { |
|
|
if (status == BluetoothGatt.GATT_SUCCESS) { |
|
|
FileLogger.i(TAG, "MTU 更新成功: $mtu") |
|
|
Log.i(TAG, "MTU 更新成功: $mtu") |
|
|
configureOTA() |
|
|
configureOTA() |
|
|
|
|
|
|
|
|
startOTA() |
|
|
startOTA() |
|
|
} else { |
|
|
} else { |
|
|
FileLogger.e(TAG, "MTU 更新失败: status=$status") |
|
|
Log.e(TAG, "MTU 更新失败: status=$status") |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -499,7 +497,7 @@ object BleService { |
|
|
status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED -> { |
|
|
status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED -> { |
|
|
updateConnectionState(BleConst.STATE_CONNECTED) |
|
|
updateConnectionState(BleConst.STATE_CONNECTED) |
|
|
g.discoverServices() |
|
|
g.discoverServices() |
|
|
FileLogger.i(TAG, "连接成功,开始 MTU 协商") |
|
|
Log.i(TAG, "连接成功,开始 MTU 协商") |
|
|
|
|
|
|
|
|
otaManager?.onBtDeviceConnection(g.device, StateCode.CONNECTION_OK) |
|
|
otaManager?.onBtDeviceConnection(g.device, StateCode.CONNECTION_OK) |
|
|
g.requestMtu(512) // 触发 MTU 修改流程 |
|
|
g.requestMtu(512) // 触发 MTU 修改流程 |
|
|
@ -538,7 +536,7 @@ object BleService { |
|
|
audioChar = audioSvc?.getCharacteristic(BleConst.RECEIVE_AUDIO_CHAR_UUID) |
|
|
audioChar = audioSvc?.getCharacteristic(BleConst.RECEIVE_AUDIO_CHAR_UUID) |
|
|
|
|
|
|
|
|
if (notifyChar == null || writeChar == null) { |
|
|
if (notifyChar == null || writeChar == null) { |
|
|
FileLogger.e(TAG, "未找到主服务所需特征") |
|
|
Log.e(TAG, "未找到主服务所需特征") |
|
|
updateConnectionState(BleConst.STATE_ERROR) |
|
|
updateConnectionState(BleConst.STATE_ERROR) |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
@ -548,9 +546,9 @@ object BleService { |
|
|
// 设置音频服务的通知(如果存在) |
|
|
// 设置音频服务的通知(如果存在) |
|
|
if (audioChar != null) { |
|
|
if (audioChar != null) { |
|
|
setupNotifications(g, audioChar) |
|
|
setupNotifications(g, audioChar) |
|
|
FileLogger.i(TAG, "音频服务特征找到并设置通知") |
|
|
Log.i(TAG, "音频服务特征找到并设置通知") |
|
|
} else { |
|
|
} else { |
|
|
FileLogger.w(TAG, "音频服务特征未找到") |
|
|
Log.w(TAG, "音频服务特征未找到") |
|
|
} |
|
|
} |
|
|
// 设置主服务的通知 |
|
|
// 设置主服务的通知 |
|
|
setupNotifications(g, notifyChar) |
|
|
setupNotifications(g, notifyChar) |
|
|
@ -566,12 +564,12 @@ object BleService { |
|
|
when (c.uuid) { |
|
|
when (c.uuid) { |
|
|
// 音频特征数据 |
|
|
// 音频特征数据 |
|
|
BleConst.RECEIVE_AUDIO_CHAR_UUID -> { |
|
|
BleConst.RECEIVE_AUDIO_CHAR_UUID -> { |
|
|
FileLogger.i(TAG, "收到音频特征数据") |
|
|
// Log.i(TAG, "收到音频特征数据") |
|
|
processAudioData(data) |
|
|
processAudioData(data) |
|
|
} |
|
|
} |
|
|
// 通知特征数据(命令和控制) |
|
|
// 通知特征数据(命令和控制) |
|
|
BleConst.NOTIFY_CHAR_UUID -> { |
|
|
BleConst.NOTIFY_CHAR_UUID -> { |
|
|
FileLogger.i(TAG, "收到通知特征数据(命令和控制)") |
|
|
// Log.i(TAG, "收到通知特征数据(命令和控制)") |
|
|
// 判断数据类型 |
|
|
// 判断数据类型 |
|
|
when { |
|
|
when { |
|
|
// 设备响应 (0xBB开头) |
|
|
// 设备响应 (0xBB开头) |
|
|
@ -584,7 +582,7 @@ object BleService { |
|
|
} |
|
|
} |
|
|
// 其他未知数据 |
|
|
// 其他未知数据 |
|
|
else -> { |
|
|
else -> { |
|
|
FileLogger.d( |
|
|
Log.d( |
|
|
TAG, |
|
|
TAG, |
|
|
"收到未知数据: ${data.joinToString(", ") { "0x%02X".format(it) }}" |
|
|
"收到未知数据: ${data.joinToString(", ") { "0x%02X".format(it) }}" |
|
|
) |
|
|
) |
|
|
@ -593,8 +591,7 @@ object BleService { |
|
|
} |
|
|
} |
|
|
// 其他未知特征 |
|
|
// 其他未知特征 |
|
|
else -> { |
|
|
else -> { |
|
|
FileLogger.i(TAG, "收到其他未知特征") |
|
|
Log.d( |
|
|
FileLogger.d( |
|
|
|
|
|
TAG, |
|
|
TAG, |
|
|
"收到未知特征数据: ${c.uuid}, 数据=${ |
|
|
"收到未知特征数据: ${c.uuid}, 数据=${ |
|
|
data.joinToString(", ") { |
|
|
data.joinToString(", ") { |
|
|
@ -609,7 +606,7 @@ object BleService { |
|
|
override fun onCharacteristicWrite( |
|
|
override fun onCharacteristicWrite( |
|
|
g: BluetoothGatt, c: BluetoothGattCharacteristic, status: Int |
|
|
g: BluetoothGatt, c: BluetoothGattCharacteristic, status: Int |
|
|
) { |
|
|
) { |
|
|
FileLogger.i( |
|
|
Log.i( |
|
|
TAG, |
|
|
TAG, |
|
|
"写入 ${if (status == BluetoothGatt.GATT_SUCCESS) "成功" else "失败"}" |
|
|
"写入 ${if (status == BluetoothGatt.GATT_SUCCESS) "成功" else "失败"}" |
|
|
) |
|
|
) |
|
|
@ -618,10 +615,8 @@ object BleService { |
|
|
override fun onDescriptorWrite( |
|
|
override fun onDescriptorWrite( |
|
|
g: BluetoothGatt, d: BluetoothGattDescriptor, status: Int |
|
|
g: BluetoothGatt, d: BluetoothGattDescriptor, status: Int |
|
|
) { |
|
|
) { |
|
|
if (status == BluetoothGatt.GATT_SUCCESS) { |
|
|
if (status == BluetoothGatt.GATT_SUCCESS) |
|
|
FileLogger.i(TAG, "通知描述符写入成功: ${d.characteristic.uuid}") |
|
|
Log.i(TAG, "通知描述符写入成功: ${d.characteristic.uuid}") |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -630,7 +625,7 @@ object BleService { |
|
|
*/ |
|
|
*/ |
|
|
private fun setupNotifications(g: BluetoothGatt, characteristic: BluetoothGattCharacteristic?) { |
|
|
private fun setupNotifications(g: BluetoothGatt, characteristic: BluetoothGattCharacteristic?) { |
|
|
if (characteristic == null || characteristic.properties.and(BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0) { |
|
|
if (characteristic == null || characteristic.properties.and(BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0) { |
|
|
FileLogger.w(TAG, "特征不支持通知功能: ${characteristic?.uuid}") |
|
|
Log.w(TAG, "特征不支持通知功能: ${characteristic?.uuid}") |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -649,10 +644,10 @@ object BleService { |
|
|
if (opusManager?.isDecodeStream == true) { |
|
|
if (opusManager?.isDecodeStream == true) { |
|
|
opusManager?.writeAudioStream(data) |
|
|
opusManager?.writeAudioStream(data) |
|
|
} else { |
|
|
} else { |
|
|
// FileLogger.d(TAG, "Opus解码流未启动,忽略音频数据") |
|
|
// Log.d(TAG, "Opus解码流未启动,忽略音频数据") |
|
|
} |
|
|
} |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "处理音频数据异常: ${e.message}", e) |
|
|
Log.e(TAG, "处理音频数据异常: ${e.message}", e) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -661,12 +656,12 @@ object BleService { |
|
|
* 处理设备响应数据 - 帧头为0xBB |
|
|
* 处理设备响应数据 - 帧头为0xBB |
|
|
*/ |
|
|
*/ |
|
|
private fun processDeviceResponse(data: ByteArray) { |
|
|
private fun processDeviceResponse(data: ByteArray) { |
|
|
FileLogger.d( |
|
|
Log.d( |
|
|
TAG, |
|
|
TAG, |
|
|
"收到设备响应: ${data.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}" |
|
|
"收到设备响应: ${data.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}" |
|
|
) |
|
|
) |
|
|
if (data.size < 3) { |
|
|
if (data.size < 3) { |
|
|
FileLogger.e(TAG, "设备响应数据格式错误:数据长度过短") |
|
|
Log.e(TAG, "设备响应数据格式错误:数据长度过短") |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -675,7 +670,7 @@ object BleService { |
|
|
|
|
|
|
|
|
// 判断命令失败响应(长度为0) |
|
|
// 判断命令失败响应(长度为0) |
|
|
if (data.size == 4 && data[2].toInt() and 0xFF == 0) { |
|
|
if (data.size == 4 && data[2].toInt() and 0xFF == 0) { |
|
|
FileLogger.w(TAG, "命令 0x${cmdType.toString(16)} 执行失败") |
|
|
Log.w(TAG, "命令 0x${cmdType.toString(16)} 执行失败") |
|
|
// 创建失败结果Map |
|
|
// 创建失败结果Map |
|
|
val resultMap = mapOf( |
|
|
val resultMap = mapOf( |
|
|
"success" to false, |
|
|
"success" to false, |
|
|
@ -691,7 +686,7 @@ object BleService { |
|
|
|
|
|
|
|
|
// 检查数据长度 |
|
|
// 检查数据长度 |
|
|
if (data.size != length + 4) { // 帧头 + 命令 + 长度 + 数据 + CRC |
|
|
if (data.size != length + 4) { // 帧头 + 命令 + 长度 + 数据 + CRC |
|
|
FileLogger.e(TAG, "设备响应数据长度不匹配: 期望=${length + 4}, 实际=${data.size}") |
|
|
Log.e(TAG, "设备响应数据长度不匹配: 期望=${length + 4}, 实际=${data.size}") |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -701,7 +696,7 @@ object BleService { |
|
|
val receivedCrc = data[data.size - 1].toInt() and 0xFF |
|
|
val receivedCrc = data[data.size - 1].toInt() and 0xFF |
|
|
|
|
|
|
|
|
if (calculatedCrc.toInt() and 0xFF != receivedCrc) { |
|
|
if (calculatedCrc.toInt() and 0xFF != receivedCrc) { |
|
|
FileLogger.e( |
|
|
Log.e( |
|
|
TAG, |
|
|
TAG, |
|
|
"设备响应CRC校验失败: 计算=${calculatedCrc.toInt() and 0xFF}, 接收=${receivedCrc}" |
|
|
"设备响应CRC校验失败: 计算=${calculatedCrc.toInt() and 0xFF}, 接收=${receivedCrc}" |
|
|
) |
|
|
) |
|
|
@ -714,7 +709,7 @@ object BleService { |
|
|
System.arraycopy(data, 3, responseData, 0, length) |
|
|
System.arraycopy(data, 3, responseData, 0, length) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
FileLogger.d( |
|
|
Log.d( |
|
|
TAG, |
|
|
TAG, |
|
|
"收到设备响应: CMD=0x${cmdType.toString(16)}, 数据=${ |
|
|
"收到设备响应: CMD=0x${cmdType.toString(16)}, 数据=${ |
|
|
responseData.joinToString(", ") { |
|
|
responseData.joinToString(", ") { |
|
|
@ -742,7 +737,7 @@ object BleService { |
|
|
.dropWhile { it == 0xFF } // 仅丢弃开头的连续 255 |
|
|
.dropWhile { it == 0xFF } // 仅丢弃开头的连续 255 |
|
|
.joinToString(".") { it.toString() } |
|
|
.joinToString(".") { it.toString() } |
|
|
resultMap["version"] = version |
|
|
resultMap["version"] = version |
|
|
FileLogger.i(TAG, "接收到目标版本号: $version") |
|
|
Log.i(TAG, "接收到目标版本号: $version") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
@ -761,7 +756,7 @@ object BleService { |
|
|
val productId = |
|
|
val productId = |
|
|
responseData.joinToString(".") { (it.toInt() and 0xFF).toString() } |
|
|
responseData.joinToString(".") { (it.toInt() and 0xFF).toString() } |
|
|
resultMap["productId"] = productId |
|
|
resultMap["productId"] = productId |
|
|
FileLogger.i(TAG, "接收到产品ID: $productId") |
|
|
Log.i(TAG, "接收到产品ID: $productId") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
@ -777,7 +772,7 @@ object BleService { |
|
|
if (responseData.isNotEmpty()) { |
|
|
if (responseData.isNotEmpty()) { |
|
|
val colorId = (responseData[0].toInt() and 0xFF).toString() |
|
|
val colorId = (responseData[0].toInt() and 0xFF).toString() |
|
|
resultMap["colorId"] = colorId |
|
|
resultMap["colorId"] = colorId |
|
|
FileLogger.i(TAG, "接收到耳机颜色ID: $colorId") |
|
|
Log.i(TAG, "接收到耳机颜色ID: $colorId") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
@ -814,7 +809,7 @@ object BleService { |
|
|
resultMap["caseCharging"] = caseCharging |
|
|
resultMap["caseCharging"] = caseCharging |
|
|
resultMap["batteryLevel"] = leftEarBattery // 整体电量用左耳表示 |
|
|
resultMap["batteryLevel"] = leftEarBattery // 整体电量用左耳表示 |
|
|
|
|
|
|
|
|
FileLogger.i( |
|
|
Log.i( |
|
|
TAG, "接收到电量信息: 左耳=${leftEarBattery}% " + |
|
|
TAG, "接收到电量信息: 左耳=${leftEarBattery}% " + |
|
|
"(${if (leftEarCharging) "充电中" else "未充电"}), 右耳=${rightEarBattery}% " + |
|
|
"(${if (leftEarCharging) "充电中" else "未充电"}), 右耳=${rightEarBattery}% " + |
|
|
"(${if (rightEarCharging) "充电中" else "未充电"}), 充电仓=${caseBattery}% " + |
|
|
"(${if (rightEarCharging) "充电中" else "未充电"}), 充电仓=${caseBattery}% " + |
|
|
@ -858,7 +853,7 @@ object BleService { |
|
|
resultMap["statusDesc"] = statusDesc |
|
|
resultMap["statusDesc"] = statusDesc |
|
|
resultMap["channelDesc"] = channelDesc |
|
|
resultMap["channelDesc"] = channelDesc |
|
|
|
|
|
|
|
|
FileLogger.i(TAG, "编解码控制响应: $statusDesc, $channelDesc") |
|
|
Log.i(TAG, "编解码控制响应: $statusDesc, $channelDesc") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
@ -872,7 +867,7 @@ object BleService { |
|
|
"rawData" to responseData, |
|
|
"rawData" to responseData, |
|
|
"isUnknown" to true |
|
|
"isUnknown" to true |
|
|
) |
|
|
) |
|
|
FileLogger.d(TAG, "收到未知命令响应: 0x${cmdType.toString(16)}") |
|
|
Log.d(TAG, "收到未知命令响应: 0x${cmdType.toString(16)}") |
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
notifyDeviceInfoReceived(cmdType, resultMap) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -882,12 +877,12 @@ object BleService { |
|
|
* 处理设备主动上报数据 - 帧头为0xCC |
|
|
* 处理设备主动上报数据 - 帧头为0xCC |
|
|
*/ |
|
|
*/ |
|
|
private fun processDeviceNotification(data: ByteArray) { |
|
|
private fun processDeviceNotification(data: ByteArray) { |
|
|
FileLogger.d( |
|
|
Log.d( |
|
|
TAG, |
|
|
TAG, |
|
|
"收到设备主动上报: ${data.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}" |
|
|
"收到设备主动上报: ${data.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}" |
|
|
) |
|
|
) |
|
|
if (data.size < 3) { |
|
|
if (data.size < 3) { |
|
|
FileLogger.e(TAG, "设备主动上报数据格式错误:数据长度过短") |
|
|
Log.e(TAG, "设备主动上报数据格式错误:数据长度过短") |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -897,7 +892,7 @@ object BleService { |
|
|
|
|
|
|
|
|
// 检查数据长度 |
|
|
// 检查数据长度 |
|
|
if (data.size != length + 4) { // 帧头 + 类型 + 长度 + 数据 + CRC |
|
|
if (data.size != length + 4) { // 帧头 + 类型 + 长度 + 数据 + CRC |
|
|
FileLogger.e(TAG, "设备主动上报数据长度不匹配: 期望=${length + 4}, 实际=${data.size}") |
|
|
Log.e(TAG, "设备主动上报数据长度不匹配: 期望=${length + 4}, 实际=${data.size}") |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -907,7 +902,7 @@ object BleService { |
|
|
val receivedCrc = data[data.size - 1].toInt() and 0xFF |
|
|
val receivedCrc = data[data.size - 1].toInt() and 0xFF |
|
|
|
|
|
|
|
|
if (calculatedCrc.toInt() and 0xFF != receivedCrc) { |
|
|
if (calculatedCrc.toInt() and 0xFF != receivedCrc) { |
|
|
FileLogger.e( |
|
|
Log.e( |
|
|
TAG, |
|
|
TAG, |
|
|
"设备主动上报CRC校验失败: 计算=${calculatedCrc.toInt() and 0xFF}, 接收=${receivedCrc}" |
|
|
"设备主动上报CRC校验失败: 计算=${calculatedCrc.toInt() and 0xFF}, 接收=${receivedCrc}" |
|
|
) |
|
|
) |
|
|
@ -920,7 +915,7 @@ object BleService { |
|
|
System.arraycopy(data, 3, notifyData, 0, length) |
|
|
System.arraycopy(data, 3, notifyData, 0, length) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
FileLogger.d( |
|
|
Log.d( |
|
|
TAG, |
|
|
TAG, |
|
|
"收到设备主动上报: 类型=0x${infoType.toString(16)}, 数据=${ |
|
|
"收到设备主动上报: 类型=0x${infoType.toString(16)}, 数据=${ |
|
|
notifyData.joinToString(", ") { |
|
|
notifyData.joinToString(", ") { |
|
|
@ -965,7 +960,7 @@ object BleService { |
|
|
resultMap["caseCharging"] = caseCharging |
|
|
resultMap["caseCharging"] = caseCharging |
|
|
resultMap["batteryLevel"] = leftEarBattery // 整体电量用左耳表示 |
|
|
resultMap["batteryLevel"] = leftEarBattery // 整体电量用左耳表示 |
|
|
|
|
|
|
|
|
FileLogger.i( |
|
|
Log.i( |
|
|
TAG, "收到主动上报电量信息: 左耳=${leftEarBattery}% " + |
|
|
TAG, "收到主动上报电量信息: 左耳=${leftEarBattery}% " + |
|
|
"(${if (leftEarCharging) "充电中" else "未充电"}), 右耳=${rightEarBattery}% " + |
|
|
"(${if (leftEarCharging) "充电中" else "未充电"}), 右耳=${rightEarBattery}% " + |
|
|
"(${if (rightEarCharging) "充电中" else "未充电"}), 充电仓=${caseBattery}% " + |
|
|
"(${if (rightEarCharging) "充电中" else "未充电"}), 充电仓=${caseBattery}% " + |
|
|
@ -977,7 +972,7 @@ object BleService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
BleConst.CMD_WAKE_UP -> { |
|
|
BleConst.CMD_WAKE_UP -> { |
|
|
FileLogger.i(TAG, "收到唤醒指令") |
|
|
Log.i(TAG, "收到唤醒指令") |
|
|
// 接收到唤醒信号,打开编码器 (设备侧) |
|
|
// 接收到唤醒信号,打开编码器 (设备侧) |
|
|
openEncoder() |
|
|
openEncoder() |
|
|
notifyWakeupSignalReceived() |
|
|
notifyWakeupSignalReceived() |
|
|
@ -993,7 +988,7 @@ object BleService { |
|
|
"isUnknown" to true, |
|
|
"isUnknown" to true, |
|
|
"isNotification" to true // 标记为主动上报 |
|
|
"isNotification" to true // 标记为主动上报 |
|
|
) |
|
|
) |
|
|
FileLogger.d(TAG, "收到未知主动上报类型: 0x${infoType.toString(16)}") |
|
|
Log.d(TAG, "收到未知主动上报类型: 0x${infoType.toString(16)}") |
|
|
notifyDeviceInfoReceived(infoType, resultMap) |
|
|
notifyDeviceInfoReceived(infoType, resultMap) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1010,13 +1005,13 @@ object BleService { |
|
|
packetSize: Int = 40 // 确认设备端Opus编码帧长 |
|
|
packetSize: Int = 40 // 确认设备端Opus编码帧长 |
|
|
): Boolean { |
|
|
): Boolean { |
|
|
if (opusManager == null) { |
|
|
if (opusManager == null) { |
|
|
FileLogger.e(TAG, "OpusManager未初始化,无法开始解码") |
|
|
Log.e(TAG, "OpusManager未初始化,无法开始解码") |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
// 如果已经在解码流,先停止 |
|
|
// 如果已经在解码流,先停止 |
|
|
if (opusManager?.isDecodeStream == true) { |
|
|
if (opusManager?.isDecodeStream == true) { |
|
|
opusManager?.stopDecodeStream() |
|
|
opusManager?.stopDecodeStream() |
|
|
FileLogger.d(TAG, "已停止正在进行的Opus解码流") |
|
|
Log.d(TAG, "已停止正在进行的Opus解码流") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val option = OpusOption() |
|
|
val option = OpusOption() |
|
|
@ -1025,29 +1020,29 @@ object BleService { |
|
|
.setSampleRate(sampleRate) |
|
|
.setSampleRate(sampleRate) |
|
|
.setPacketSize(packetSize) |
|
|
.setPacketSize(packetSize) |
|
|
|
|
|
|
|
|
FileLogger.d(TAG, "准备开始Opus数据流解码, 参数: $option") |
|
|
Log.d(TAG, "准备开始Opus数据流解码, 参数: $option") |
|
|
|
|
|
|
|
|
var streamStartedSuccessfully = false |
|
|
var streamStartedSuccessfully = false |
|
|
opusManager?.startDecodeStream(option, object : OnDecodeStreamCallback { |
|
|
opusManager?.startDecodeStream(option, object : OnDecodeStreamCallback { |
|
|
override fun onDecodeStream(data: ByteArray?) { |
|
|
override fun onDecodeStream(data: ByteArray?) { |
|
|
if (data != null) { |
|
|
if (data != null) { |
|
|
// FileLogger.d(TAG, "Opus解码数据: ${data.size} bytes") |
|
|
// Log.d(TAG, "Opus解码数据: ${data.size} bytes") |
|
|
notifyAudioDataReceived(data) |
|
|
notifyAudioDataReceived(data) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
override fun onStart() { |
|
|
override fun onStart() { |
|
|
streamStartedSuccessfully = true |
|
|
streamStartedSuccessfully = true |
|
|
FileLogger.i(TAG, "Opus数据流解码已开始") |
|
|
Log.i(TAG, "Opus数据流解码已开始") |
|
|
// 可以通过回调通知上层解码已开始 |
|
|
// 可以通过回调通知上层解码已开始 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
override fun onComplete(outPath: String?) { |
|
|
override fun onComplete(outPath: String?) { |
|
|
FileLogger.i(TAG, "Opus数据流解码完成: $outPath (通常流式解码不会调用此方法)") |
|
|
Log.i(TAG, "Opus数据流解码完成: $outPath (通常流式解码不会调用此方法)") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
override fun onError(code: Int, message: String?) { |
|
|
override fun onError(code: Int, message: String?) { |
|
|
FileLogger.e(TAG, "Opus数据流解码错误: [$code] $message") |
|
|
Log.e(TAG, "Opus数据流解码错误: [$code] $message") |
|
|
// 可以通过回调通知上层解码错误 |
|
|
// 可以通过回调通知上层解码错误 |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
@ -1060,10 +1055,10 @@ object BleService { |
|
|
private fun stopOpusStreamDecoding(): Boolean { |
|
|
private fun stopOpusStreamDecoding(): Boolean { |
|
|
if (opusManager?.isDecodeStream == true) { |
|
|
if (opusManager?.isDecodeStream == true) { |
|
|
opusManager?.stopDecodeStream() |
|
|
opusManager?.stopDecodeStream() |
|
|
FileLogger.i(TAG, "已停止Opus数据流解码") |
|
|
Log.i(TAG, "已停止Opus数据流解码") |
|
|
return true |
|
|
return true |
|
|
} |
|
|
} |
|
|
FileLogger.d(TAG, "Opus数据流未在解码或OpusManager未初始化") |
|
|
Log.d(TAG, "Opus数据流未在解码或OpusManager未初始化") |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1075,7 +1070,7 @@ object BleService { |
|
|
* 获取耳机版本号 |
|
|
* 获取耳机版本号 |
|
|
*/ |
|
|
*/ |
|
|
fun getDeviceVersion(): Boolean { |
|
|
fun getDeviceVersion(): Boolean { |
|
|
FileLogger.i(TAG, "获取耳机版本号...") |
|
|
Log.i(TAG, "获取耳机版本号...") |
|
|
return sendCommand(BleConst.CMD_GET_VERSION.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
return sendCommand(BleConst.CMD_GET_VERSION.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1083,7 +1078,7 @@ object BleService { |
|
|
* 获取产品ID |
|
|
* 获取产品ID |
|
|
*/ |
|
|
*/ |
|
|
fun getProductId(): Boolean { |
|
|
fun getProductId(): Boolean { |
|
|
FileLogger.i(TAG, "获取耳机产品ID...") |
|
|
Log.i(TAG, "获取耳机产品ID...") |
|
|
return sendCommand(BleConst.CMD_GET_PRODUCT_ID.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
return sendCommand(BleConst.CMD_GET_PRODUCT_ID.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1091,7 +1086,7 @@ object BleService { |
|
|
* 获取耳机颜色ID |
|
|
* 获取耳机颜色ID |
|
|
*/ |
|
|
*/ |
|
|
fun getColorId(): Boolean { |
|
|
fun getColorId(): Boolean { |
|
|
FileLogger.i(TAG, "获取耳机颜色ID...") |
|
|
Log.i(TAG, "获取耳机颜色ID...") |
|
|
return sendCommand(BleConst.CMD_GET_COLOR_ID.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
return sendCommand(BleConst.CMD_GET_COLOR_ID.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1099,7 +1094,7 @@ object BleService { |
|
|
* 获取耳机电量信息 |
|
|
* 获取耳机电量信息 |
|
|
*/ |
|
|
*/ |
|
|
fun getBatteryInfo(): Boolean { |
|
|
fun getBatteryInfo(): Boolean { |
|
|
FileLogger.i(TAG, "获取耳机电量信息...") |
|
|
Log.i(TAG, "获取耳机电量信息...") |
|
|
return sendCommand(BleConst.CMD_GET_BATTERY_INFO.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
return sendCommand(BleConst.CMD_GET_BATTERY_INFO.toByte(), byteArrayOf(0xFF.toByte())) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1107,7 +1102,7 @@ object BleService { |
|
|
* 控制编解码 - 关闭编解码 |
|
|
* 控制编解码 - 关闭编解码 |
|
|
*/ |
|
|
*/ |
|
|
fun closeCodec(): Boolean { |
|
|
fun closeCodec(): Boolean { |
|
|
FileLogger.i(TAG, "关闭编解码...") |
|
|
Log.i(TAG, "关闭编解码...") |
|
|
|
|
|
|
|
|
return sendCommand( |
|
|
return sendCommand( |
|
|
BleConst.CMD_CONTROL_CODEC.toByte(), |
|
|
BleConst.CMD_CONTROL_CODEC.toByte(), |
|
|
@ -1123,7 +1118,7 @@ object BleService { |
|
|
* 控制编解码 - 打开解码 |
|
|
* 控制编解码 - 打开解码 |
|
|
*/ |
|
|
*/ |
|
|
fun openDecoder(): Boolean { |
|
|
fun openDecoder(): Boolean { |
|
|
FileLogger.i(TAG, "打开编码 (设备侧)...") |
|
|
Log.i(TAG, "打开编码 (设备侧)...") |
|
|
|
|
|
|
|
|
// val opusStarted = startOpusStreamDecoding( |
|
|
// val opusStarted = startOpusStreamDecoding( |
|
|
// hasHeader = false, // BLE传输的Opus数据通常无文件头 |
|
|
// hasHeader = false, // BLE传输的Opus数据通常无文件头 |
|
|
@ -1136,7 +1131,7 @@ object BleService { |
|
|
// ) |
|
|
// ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FileLogger.i(TAG, "打开解码...") |
|
|
Log.i(TAG, "打开解码...") |
|
|
return sendCommand( |
|
|
return sendCommand( |
|
|
BleConst.CMD_CONTROL_CODEC.toByte(), byteArrayOf( |
|
|
BleConst.CMD_CONTROL_CODEC.toByte(), byteArrayOf( |
|
|
BleConst.CODEC_CONTROL_DECODE_ON.toByte(), |
|
|
BleConst.CODEC_CONTROL_DECODE_ON.toByte(), |
|
|
@ -1150,9 +1145,9 @@ object BleService { |
|
|
* 控制编解码 - 打开解码 |
|
|
* 控制编解码 - 打开解码 |
|
|
*/ |
|
|
*/ |
|
|
fun openA2DPDecoder(): Boolean { |
|
|
fun openA2DPDecoder(): Boolean { |
|
|
FileLogger.i(TAG, "打开编码 (设备侧)...") |
|
|
Log.i(TAG, "打开编码 (设备侧)...") |
|
|
|
|
|
|
|
|
// FileLogger.i(TAG, "打开解码...") |
|
|
// Log.i(TAG, "打开解码...") |
|
|
return sendCommand( |
|
|
return sendCommand( |
|
|
BleConst.CMD_CONTROL_CODEC.toByte(), byteArrayOf( |
|
|
BleConst.CMD_CONTROL_CODEC.toByte(), byteArrayOf( |
|
|
BleConst.CODEC_CONTROL_A2DP_PLAY.toByte(), |
|
|
BleConst.CODEC_CONTROL_A2DP_PLAY.toByte(), |
|
|
@ -1166,7 +1161,7 @@ object BleService { |
|
|
* 控制编解码 - A2DP播放 |
|
|
* 控制编解码 - A2DP播放 |
|
|
*/ |
|
|
*/ |
|
|
fun playA2DP(): Boolean { |
|
|
fun playA2DP(): Boolean { |
|
|
FileLogger.i(TAG, "切换至A2DP播放模式...") |
|
|
Log.i(TAG, "切换至A2DP播放模式...") |
|
|
return sendCommand(BleConst.CMD_PLAY_A2DP.toByte()) |
|
|
return sendCommand(BleConst.CMD_PLAY_A2DP.toByte()) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1174,7 +1169,7 @@ object BleService { |
|
|
* 控制编解码 - 打开编码 |
|
|
* 控制编解码 - 打开编码 |
|
|
*/ |
|
|
*/ |
|
|
fun openEncoder(): Boolean { |
|
|
fun openEncoder(): Boolean { |
|
|
FileLogger.i(TAG, "打开编码 (设备侧)...") |
|
|
Log.i(TAG, "打开编码 (设备侧)...") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 目前仅发送命令通知设备开始编码。 |
|
|
// 目前仅发送命令通知设备开始编码。 |
|
|
@ -1194,11 +1189,11 @@ object BleService { |
|
|
*/ |
|
|
*/ |
|
|
fun setChannelMode(channelMode: Int): Boolean { |
|
|
fun setChannelMode(channelMode: Int): Boolean { |
|
|
when (channelMode) { |
|
|
when (channelMode) { |
|
|
BleConst.AUDIO_CHANNEL_LEFT -> FileLogger.i(TAG, "设置左声道模式...") |
|
|
BleConst.AUDIO_CHANNEL_LEFT -> Log.i(TAG, "设置左声道模式...") |
|
|
BleConst.AUDIO_CHANNEL_RIGHT -> FileLogger.i(TAG, "设置右声道模式...") |
|
|
BleConst.AUDIO_CHANNEL_RIGHT -> Log.i(TAG, "设置右声道模式...") |
|
|
BleConst.AUDIO_CHANNEL_STEREO -> FileLogger.i(TAG, "设置立体声模式...") |
|
|
BleConst.AUDIO_CHANNEL_STEREO -> Log.i(TAG, "设置立体声模式...") |
|
|
else -> { |
|
|
else -> { |
|
|
FileLogger.e(TAG, "无效的声道模式: $channelMode") |
|
|
Log.e(TAG, "无效的声道模式: $channelMode") |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1216,7 +1211,7 @@ object BleService { |
|
|
* 音量增大 |
|
|
* 音量增大 |
|
|
*/ |
|
|
*/ |
|
|
fun volumeUp(): Boolean { |
|
|
fun volumeUp(): Boolean { |
|
|
FileLogger.i(TAG, "设备音量增加...") |
|
|
Log.i(TAG, "设备音量增加...") |
|
|
return sendCommand(BleConst.CMD_VOLUME_UP.toByte()) |
|
|
return sendCommand(BleConst.CMD_VOLUME_UP.toByte()) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1224,7 +1219,7 @@ object BleService { |
|
|
* 音量减小 |
|
|
* 音量减小 |
|
|
*/ |
|
|
*/ |
|
|
fun volumeDown(): Boolean { |
|
|
fun volumeDown(): Boolean { |
|
|
FileLogger.i(TAG, "设备音量减小...") |
|
|
Log.i(TAG, "设备音量减小...") |
|
|
return sendCommand(BleConst.CMD_VOLUME_DOWN.toByte()) |
|
|
return sendCommand(BleConst.CMD_VOLUME_DOWN.toByte()) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1278,7 +1273,7 @@ object BleService { |
|
|
it.release() |
|
|
it.release() |
|
|
} |
|
|
} |
|
|
opusManager = null |
|
|
opusManager = null |
|
|
FileLogger.d(TAG, "OpusManager已释放") |
|
|
Log.d(TAG, "OpusManager已释放") |
|
|
isInitialized = false // 标记为未初始化 |
|
|
isInitialized = false // 标记为未初始化 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1294,7 +1289,7 @@ object BleService { |
|
|
*/ |
|
|
*/ |
|
|
private fun sendCommand(cmdType: Byte, cmdData: ByteArray = byteArrayOf()): Boolean { |
|
|
private fun sendCommand(cmdType: Byte, cmdData: ByteArray = byteArrayOf()): Boolean { |
|
|
if (!checkConn()) { |
|
|
if (!checkConn()) { |
|
|
FileLogger.e(TAG, "发送命令失败: 设备未连接") |
|
|
Log.e(TAG, "发送命令失败: 设备未连接") |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1325,7 +1320,7 @@ object BleService { |
|
|
cmdPacket[3 + cmdLength] = crc |
|
|
cmdPacket[3 + cmdLength] = crc |
|
|
|
|
|
|
|
|
// 记录命令详情 |
|
|
// 记录命令详情 |
|
|
FileLogger.d( |
|
|
Log.d( |
|
|
TAG, |
|
|
TAG, |
|
|
"发送命令: CMD=0x${(cmdType.toInt() and 0xFF).toString(16)}, 长度=$cmdLength, " + |
|
|
"发送命令: CMD=0x${(cmdType.toInt() and 0xFF).toString(16)}, 长度=$cmdLength, " + |
|
|
"数据=${cmdData.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}, " + |
|
|
"数据=${cmdData.joinToString(", ") { "0x${(it.toInt() and 0xFF).toString(16)}" }}, " + |
|
|
@ -1336,7 +1331,7 @@ object BleService { |
|
|
writeChar!!.value = cmdPacket |
|
|
writeChar!!.value = cmdPacket |
|
|
return bluetoothGatt?.writeCharacteristic(writeChar) ?: false |
|
|
return bluetoothGatt?.writeCharacteristic(writeChar) ?: false |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "发送命令异常: ${e.message}", e) |
|
|
Log.e(TAG, "发送命令异常: ${e.message}", e) |
|
|
return false |
|
|
return false |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1369,7 +1364,7 @@ object BleService { |
|
|
try { |
|
|
try { |
|
|
callback.onScanResult(devices) |
|
|
callback.onScanResult(devices) |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "分发扫描结果回调异常", e) |
|
|
Log.e(TAG, "分发扫描结果回调异常", e) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1382,7 +1377,7 @@ object BleService { |
|
|
try { |
|
|
try { |
|
|
callback.onConnectionStateChanged(state) |
|
|
callback.onConnectionStateChanged(state) |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "分发连接状态回调异常", e) |
|
|
Log.e(TAG, "分发连接状态回调异常", e) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1395,7 +1390,7 @@ object BleService { |
|
|
try { |
|
|
try { |
|
|
callback.onAudioDataReceived(data) |
|
|
callback.onAudioDataReceived(data) |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "分发音频数据回调异常", e) |
|
|
Log.e(TAG, "分发音频数据回调异常", e) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1408,7 +1403,7 @@ object BleService { |
|
|
try { |
|
|
try { |
|
|
callback.onWakeupSignalReceived() |
|
|
callback.onWakeupSignalReceived() |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "分发唤醒信号回调异常", e) |
|
|
Log.e(TAG, "分发唤醒信号回调异常", e) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -1421,7 +1416,7 @@ object BleService { |
|
|
try { |
|
|
try { |
|
|
callback.onDeviceInfoReceived(infoType, infoData) |
|
|
callback.onDeviceInfoReceived(infoType, infoData) |
|
|
} catch (e: Exception) { |
|
|
} catch (e: Exception) { |
|
|
FileLogger.e(TAG, "分发设备信息回调异常", e) |
|
|
Log.e(TAG, "分发设备信息回调异常", e) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|