如何在Android应用中实现类似BUMBLE的蓝牙状态实时监听功能
实现Android蓝牙状态动态感知与功能降级/恢复机制
一、监听蓝牙状态变化
Android系统会在蓝牙状态改变时发送ACTION_STATE_CHANGED广播,通过广播接收器可实时感知状态变化:
- 动态注册广播接收器(推荐在Activity/Fragment生命周期内注册,避免内存泄漏):
private val bluetoothStateReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val state = intent?.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) when (state) { BluetoothAdapter.STATE_OFF -> { // 蓝牙已关闭,执行功能降级逻辑 handleBluetoothOff() } BluetoothAdapter.STATE_ON -> { // 蓝牙已开启,恢复完整功能 handleBluetoothOn() } BluetoothAdapter.STATE_TURNING_OFF -> { // 蓝牙正在关闭,提前清理资源 prepareForBluetoothShutdown() } BluetoothAdapter.STATE_TURNING_ON -> { // 蓝牙正在开启,准备恢复操作 prepareForBluetoothStartup() } } } } // 在onResume注册,onPause注销 override fun onResume() { super.onResume() val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) registerReceiver(bluetoothStateReceiver, filter) } override fun onPause() { super.onPause() unregisterReceiver(bluetoothStateReceiver) }
二、避免蓝牙状态突变导致崩溃
在所有BLE操作前必须检查蓝牙状态,同时用异常捕获处理不可预见的情况:
- 封装蓝牙状态检查工具方法:
private fun isBluetoothEnabled(): Boolean { val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() return bluetoothAdapter != null && bluetoothAdapter.isEnabled }
- 在BLE操作前校验状态:
fun startBleScan() { if (!isBluetoothEnabled()) { showBluetoothDisabledHint() return } try { bluetoothLeScanner?.startScan(scanCallback) } catch (e: IllegalStateException) { // 捕获蓝牙未开启或资源释放后的异常 Log.e(TAG, "Failed to start BLE scan: ${e.message}") showBluetoothDisabledHint() } }
- 蓝牙关闭时主动清理资源:
private fun handleBluetoothOff() { // 停止扫描 bluetoothLeScanner?.stopScan(scanCallback) // 断开所有BLE连接并释放资源 connectedGattDevices.forEach { gatt -> gatt.disconnect() gatt.close() } connectedGattDevices.clear() // 更新UI提示用户开启蓝牙 updateUiForBluetoothDisabled() // 保存当前应用状态 saveAppState() }
三、保存与恢复应用状态
当蓝牙关闭时,保存应用关键状态,蓝牙恢复后自动还原操作:
- 用ViewModel临时保存状态(适合内存级临时存储):
class BleViewModel : ViewModel() { val scannedDevices = mutableStateListOf<BleDevice>() var targetDeviceUuid: String? = null var isScanning: Boolean = false }
- 用SharedPreferences持久化保存(适合应用重启后恢复):
private fun saveAppState() { val prefs = getSharedPreferences("BleAppState", Context.MODE_PRIVATE) prefs.edit() .putString("targetDeviceUuid", targetDeviceUuid) .putBoolean("isScanning", isScanning) .apply() } private fun restoreAppState() { val prefs = getSharedPreferences("BleAppState", Context.MODE_PRIVATE) targetDeviceUuid = prefs.getString("targetDeviceUuid", null) isScanning = prefs.getBoolean("isScanning", false) }
- 蓝牙开启后恢复功能:
private fun handleBluetoothOn() { restoreAppState() // 恢复之前的操作 if (isScanning) { startBleScan() } targetDeviceUuid?.let { uuid -> connectToBleDevice(uuid) } // 更新UI到正常状态 updateUiForBluetoothEnabled() }
四、优化用户体验
- 引导用户开启蓝牙:检测到蓝牙关闭时,弹出系统对话框请求开启:
private fun requestEnableBluetooth() { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) } // 处理开启结果 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_ENABLE_BT) { if (resultCode == RESULT_OK) { handleBluetoothOn() } else { // 用户拒绝开启,保持降级状态 updateUiForBluetoothDisabled() } } }
- 通知栏提示:可发送持续性通知,告知用户蓝牙对应用的重要性,方便快速跳转开启。
内容的提问来源于stack exchange,提问作者Shuvam Mandal
相关产品推荐
相关产品推荐

