如何为广播接收器分配动作?onCreate中添加ACTION_ACL_DISCONNECTED方法
兄弟,我太懂你这种「连接能触发回调,但断开死活没反应」的郁闷了!其实问题大概率出在广播接收器的注册逻辑或者权限配置上,尤其是Android版本迭代后蓝牙权限的变化,很容易踩坑。下面一步步给你捋清楚怎么在onCreate里正确配置BluetoothDevice.ACTION_ACL_DISCONNECTED:
第一步:先搞定权限(重中之重)
Android不同版本对蓝牙权限的要求不一样,先把清单文件和动态权限申请做好,不然广播根本接收不到:
- 在
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" />
- 在
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_CONNECTED和ACTION_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




