|
|
|
@ -140,6 +140,21 @@ object BleService { |
|
|
|
|
|
|
|
// 初始化状态 |
|
|
|
private var isInitialized = false |
|
|
|
|
|
|
|
/** |
|
|
|
* 检查是否有蓝牙扫描权限 |
|
|
|
*/ |
|
|
|
private fun hasBluetoothScanPermission(): Boolean { |
|
|
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { |
|
|
|
// Android 12+ 需要 BLUETOOTH_SCAN 权限 |
|
|
|
context.checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) == |
|
|
|
android.content.pm.PackageManager.PERMISSION_GRANTED |
|
|
|
} else { |
|
|
|
// Android 12 以下使用 ACCESS_FINE_LOCATION 权限 |
|
|
|
context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == |
|
|
|
android.content.pm.PackageManager.PERMISSION_GRANTED |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 音频数据统计相关变量 |
|
|
|
private var bytesReceivedInCurrentSecond = 0 |
|
|
|
@ -280,18 +295,22 @@ object BleService { |
|
|
|
|
|
|
|
/** |
|
|
|
* 开始主动扫描BLE设备 |
|
|
|
* @param uuids 要扫描的服务UUID列表 |
|
|
|
* @param timeout 扫描超时时间(毫秒) |
|
|
|
* @return 是否成功开始扫描 |
|
|
|
*/ |
|
|
|
fun startScan(uuids: List<String>, timeout: Long = 15000): Boolean { |
|
|
|
// Log.i(TAG, "liwei---------startScan 1 $deviceName") |
|
|
|
if (!isInitialized) { |
|
|
|
Log.e(TAG, "BLE服务未初始化") |
|
|
|
return false |
|
|
|
} |
|
|
|
// Log.i(TAG, "liwei---------startScan 2") |
|
|
|
// 获取一个局部引用,避免并发访问问题 |
|
|
|
// val scanner = bluetoothLeScanner ?: return false |
|
|
|
|
|
|
|
// 检查蓝牙扫描权限 |
|
|
|
if (!hasBluetoothScanPermission()) { |
|
|
|
Log.e(TAG, "开始扫描失败: 缺少 BLUETOOTH_SCAN 权限") |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// 💡 每次都重新取最新实例 |
|
|
|
val scanner = bluetoothLeScanner ?: run { |
|
|
|
Log.e(TAG, "bluetoothLeScanner == null,尝试重启蓝牙") |
|
|
|
@ -299,58 +318,65 @@ object BleService { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// Log.i(TAG, "liwei---------startScan 3") |
|
|
|
if (isScanning) return false |
|
|
|
// Log.i(TAG, "liwei---------startScan 4") |
|
|
|
|
|
|
|
Log.i(TAG, "开始主动扫描BLE设备...") |
|
|
|
scanResults.clear() |
|
|
|
// Log.i(TAG, "liwei---------startScan 5") |
|
|
|
val filter = ScanFilter.Builder() |
|
|
|
// .setServiceUuid(ParcelUuid(BleConst.PRIMARY_SERVICE_UUID)) |
|
|
|
// .setServiceUuid(ParcelUuid(java.util.UUID.fromString("00000201-0000-1000-8000-00805f9b34fb"))) |
|
|
|
.build() |
|
|
|
// val filters = uuids.mapNotNull { uuidStr -> |
|
|
|
// try { |
|
|
|
// // 清理UUID字符串,移除非十六进制字符 |
|
|
|
// val cleanUuidStr = uuidStr.replace("[^0-9A-Fa-f]".toRegex(), "") |
|
|
|
// |
|
|
|
// // 验证清理后的字符串长度(应该是4位十六进制字符) |
|
|
|
// if (cleanUuidStr.length != 4) { |
|
|
|
// Log.w(TAG, "无效的UUID格式: $uuidStr,清理后: $cleanUuidStr,长度: ${cleanUuidStr.length}") |
|
|
|
// return@mapNotNull null |
|
|
|
// } |
|
|
|
// |
|
|
|
// val fullUuid = "0000$cleanUuidStr-0000-1000-8000-00805f9b34fb" |
|
|
|
// Log.d(TAG, "扫描uuid: $fullUuid") |
|
|
|
// |
|
|
|
// ScanFilter.Builder() |
|
|
|
// .setServiceUuid(ParcelUuid(UUID.fromString(fullUuid))) |
|
|
|
// .build() |
|
|
|
// } catch (e: IllegalArgumentException) { |
|
|
|
// Log.e(TAG, "构造UUID失败: $uuidStr", e) |
|
|
|
// null |
|
|
|
// } |
|
|
|
// } |
|
|
|
|
|
|
|
// 构建扫描过滤器 - 参考 registerBackgroundScan 的实现 |
|
|
|
val filters = mutableListOf<ScanFilter>() |
|
|
|
|
|
|
|
// 如果提供了额外的UUID,也添加到过滤器中 |
|
|
|
uuids.forEach { uuidStr -> |
|
|
|
try { |
|
|
|
val uuid = when { |
|
|
|
uuidStr.length == 4 -> { |
|
|
|
// 短UUID,转换为完整UUID |
|
|
|
val fullUuid = "0000$uuidStr-0000-1000-8000-00805f9b34fb" |
|
|
|
UUID.fromString(fullUuid) |
|
|
|
} |
|
|
|
uuidStr.length == 36 -> { |
|
|
|
// 完整UUID |
|
|
|
UUID.fromString(uuidStr) |
|
|
|
} |
|
|
|
else -> { |
|
|
|
Log.w(TAG, "无效的UUID格式: $uuidStr") |
|
|
|
return@forEach |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val filter = ScanFilter.Builder() |
|
|
|
//.setServiceUuid(ParcelUuid(uuid)) |
|
|
|
.build() |
|
|
|
filters.add(filter) |
|
|
|
Log.d(TAG, "添加扫描过滤器UUID: $uuid") |
|
|
|
} catch (e: IllegalArgumentException) { |
|
|
|
Log.e(TAG, "构造UUID失败: $uuidStr", e) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 扫描设置 - 参考 registerBackgroundScan 的配置 |
|
|
|
val settings = ScanSettings.Builder() |
|
|
|
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER) |
|
|
|
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) // 推荐:不会触发权限问题 |
|
|
|
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) |
|
|
|
.setReportDelay(0) |
|
|
|
.build() |
|
|
|
// Log.i(TAG, "liwei---------startScan 7") |
|
|
|
|
|
|
|
try { |
|
|
|
scanner.startScan(listOf(filter), settings, scanCallback) |
|
|
|
// 使用过滤器列表进行扫描 |
|
|
|
scanner.startScan(filters, settings, scanCallback) |
|
|
|
isScanning = true |
|
|
|
// Log.i(TAG, "liwei---------startScan 8") |
|
|
|
|
|
|
|
// 设置扫描超时 |
|
|
|
scanHandler.postDelayed({ |
|
|
|
Log.d(TAG, "扫描超时,停止扫描") |
|
|
|
stopScan() |
|
|
|
}, timeout) |
|
|
|
// Log.i(TAG, "liwei---------startScan 9") |
|
|
|
|
|
|
|
Log.i(TAG, "已启动BLE扫描,过滤器数量: ${filters.size}") |
|
|
|
return true |
|
|
|
} catch (e: Exception) { |
|
|
|
Log.e(TAG, "启动扫描失败: ${e.message}", e) |
|
|
|
// Log.i(TAG, "liwei---------startScan 10") |
|
|
|
isScanning = false |
|
|
|
return false |
|
|
|
} |
|
|
|
|