You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为广播接收器分配动作?onCreate中添加ACTION_ACL_DISCONNECTED方法

兄弟,我太懂你这种「连接能触发回调,但断开死活没反应」的郁闷了!其实问题大概率出在广播接收器的注册逻辑或者权限配置上,尤其是Android版本迭代后蓝牙权限的变化,很容易踩坑。下面一步步给你捋清楚怎么在onCreate里正确配置BluetoothDevice.ACTION_ACL_DISCONNECTED

第一步:先搞定权限(重中之重)

Android不同版本对蓝牙权限的要求不一样,先把清单文件和动态权限申请做好,不然广播根本接收不到:

  1. AndroidManifest.xml里添加权限:
<!-- 基础蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- Android 12+ 必须的连接权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Android 6.0-11 需要定位权限才能监听蓝牙设备状态 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 声明设备支持蓝牙 -->
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />
  1. onCreate里动态申请权限:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 根据Android版本处理权限,权限通过后再注册广播
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        // Android 12+ 申请BLUETOOTH_CONNECT权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
            registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {
                if (isGranted) {
                    registerBluetoothReceiver();
                } else {
                    Toast.makeText(this, "需要蓝牙连接权限才能监听设备状态", Toast.LENGTH_SHORT).show();
                }
            }).launch(Manifest.permission.BLUETOOTH_CONNECT);
        } else {
            registerBluetoothReceiver();
        }
    } else {
        // Android 6.0-11 申请定位权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), permissions -> {
                boolean locationGranted = permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);
                if (locationGranted) {
                    registerBluetoothReceiver();
                } else {
                    Toast.makeText(this, "需要定位权限才能监听蓝牙设备", Toast.LENGTH_SHORT).show();
                }
            }).launch(new String[]{Manifest.permission.ACCESS_FINE_LOCATION});
        } else {
            registerBluetoothReceiver();
        }
    }
}

第二步:正确注册广播接收器

权限搞定后,写一个专门的方法注册广播,把ACTION_ACL_CONNECTEDACTION_ACL_DISCONNECTED都加入过滤器:

private BroadcastReceiver bluetoothReceiver;

private void registerBluetoothReceiver() {
    IntentFilter filter = new IntentFilter();
    // 添加连接动作
    filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
    // 添加断开动作
    filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
    // 可选:添加断开请求、配对状态变化的动作,监听更全面
    filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
    filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

    bluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device == null) return;

            if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                Toast.makeText(context, "设备已连接: " + device.getName(), Toast.LENGTH_SHORT).show();
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                Toast.makeText(context, "设备已断开: " + device.getName(), Toast.LENGTH_SHORT).show();
            }
        }
    };

    // 动态注册广播(Android 8.0+ 静态注册大部分蓝牙广播会失效)
    registerReceiver(bluetoothReceiver, filter);
}

第三步:记得注销广播,防止内存泄漏

onDestroy里注销广播接收器:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (bluetoothReceiver != null) {
        unregisterReceiver(bluetoothReceiver);
    }
}

额外注意点

  • 不要用静态注册广播:Android 8.0以后,BluetoothDevice.ACTION_ACL_*这类隐式广播无法通过静态注册接收,必须动态注册。
  • 测试断开场景:有些蓝牙耳机进入待机模式不会触发断开广播,建议手动关闭耳机或者在系统蓝牙设置里断开设备来测试。

内容的提问来源于stack exchange,提问作者user9161645

火山引擎 最新活动