You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin安卓开发:如何在onResume中正确处理蓝牙开启关闭逻辑

核心问题原因
  • 触发蓝牙开启请求的系统弹窗时,当前Activity会退至后台触发onPause回调,用户完成选择返回页面时会再次执行onResume,此时蓝牙状态还未完成更新,会重复触发请求弹窗,导致需要多次点击才能完成操作
  • 仅依赖onResume的生命周期回调无法实时捕获Activity处于前台时,用户从系统设置手动关闭蓝牙的事件,因此不会触发新的开启请求
修复方案

通过添加请求状态标记+注册蓝牙状态广播的组合方案解决:

  1. 新增isBluetoothRequestPending布尔变量,标记当前是否已经弹出了蓝牙开启请求,避免同一时间弹出多个请求
  2. 注册BluetoothAdapter.ACTION_STATE_CHANGED广播接收器,实时监听蓝牙开关状态变化,仅在蓝牙被关闭且当前没有待处理的请求时,才触发开启请求
  3. 移除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 22:45:05