Kotlin安卓开发:如何在onResume中正确处理蓝牙开启关闭逻辑
核心问题原因
- 触发蓝牙开启请求的系统弹窗时,当前Activity会退至后台触发
onPause回调,用户完成选择返回页面时会再次执行onResume,此时蓝牙状态还未完成更新,会重复触发请求弹窗,导致需要多次点击才能完成操作 - 仅依赖
onResume的生命周期回调无法实时捕获Activity处于前台时,用户从系统设置手动关闭蓝牙的事件,因此不会触发新的开启请求
修复方案
通过添加请求状态标记+注册蓝牙状态广播的组合方案解决:
- 新增
isBluetoothRequestPending布尔变量,标记当前是否已经弹出了蓝牙开启请求,避免同一时间弹出多个请求 - 注册
BluetoothAdapter.ACTION_STATE_CHANGED广播接收器,实时监听蓝牙开关状态变化,仅在蓝牙被关闭且当前没有待处理的请求时,才触发开启请求 - 移除
onResume中重复的蓝牙检测逻辑,仅在Activity首次创建时做一次状态检测
class ScanningForDevicesActivity : AppCompatActivity() { private lateinit var binding: ActivityScanningForDevicesBinding companion object{ const val BLUETOOTH_REQUEST_CODE = 1 } // 标记当前是否已经弹出蓝牙开启请求,避免重复弹出 private var isBluetoothRequestPending = false private val bluetoothAdapter: BluetoothAdapter by lazy { val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager.adapter } // 蓝牙状态变化广播接收器 private val bluetoothStateReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == BluetoothAdapter.ACTION_STATE_CHANGED) { val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) // 蓝牙被关闭,且当前没有待处理的请求时触发弹窗 if (state == BluetoothAdapter.STATE_OFF && !isBluetoothRequestPending) { promptEnableBluetooth() } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityScanningForDevicesBinding.inflate(layoutInflater) setContentView(binding.root) // 注册蓝牙状态监听广播 val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) registerReceiver(bluetoothStateReceiver, filter) // 首次进入页面检测蓝牙状态 if(!bluetoothAdapter.isEnabled && !isBluetoothRequestPending){ promptEnableBluetooth() } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if(requestCode == BLUETOOTH_REQUEST_CODE){ // 不管用户同意还是拒绝,都重置请求标记位 isBluetoothRequestPending = false if (resultCode == Activity.RESULT_CANCELED){ // 用户拒绝,返回主页面 startActivity(Intent(this, MainActivity::class.java)) finish() } } } override fun onDestroy() { super.onDestroy() // 注销广播,避免内存泄漏 unregisterReceiver(bluetoothStateReceiver) } private fun promptEnableBluetooth(){ if(!bluetoothAdapter.isEnabled && !isBluetoothRequestPending){ isBluetoothRequestPending = true val enableBluetoothIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBluetoothIntent, BLUETOOTH_REQUEST_CODE) } } }
补充说明
- 代码中新增的
isBluetoothRequestPending标记位会在弹出请求时设为true,用户操作完成后回到onActivityResult再重置为false,完全避免了重复弹窗的问题 - 广播接收器会实时监听蓝牙状态变化,只要蓝牙被关闭就会触发请求,不需要等待
onResume回调,满足用户在系统端关闭蓝牙后实时请求的需求 - 页面销毁时会注销广播,不会产生内存泄漏问题
内容的提问来源于stack exchange,提问作者matiasjhz
相关产品推荐
相关产品推荐

