Android开发如何与无PIN码的蓝牙外设完成配对通信?
Android 无PIN码蓝牙设备配对连接实现方案
不需要依赖Android Things专属接口,也不需要降低目标适配版本,通过拦截系统有序配对广播的方式即可实现标准"Just Works"无PIN配对,兼容API 18(首个支持BLE的版本)到API 34全版本普通消费级Android手机,具体实现如下:
1. 配置清单权限
根据目标SDK版本在AndroidManifest.xml中声明对应权限:
<!-- 基础蓝牙权限,全版本通用 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Android 12(API31)+ 新增蓝牙运行时权限 --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
注意:API 31及以上版本需要在代码中动态申请
BLUETOOTH_CONNECT权限,权限通过后再执行连接、配对相关操作,否则会触发安全异常。
2. 注册高优先级配对广播接收器
系统触发配对流程、弹出PIN输入框前,会发送优先级有序广播BluetoothDevice.ACTION_PAIRING_REQUEST,只要将自定义接收器的优先级设置为高于系统内置配对弹窗的优先级,就可以拦截广播,自动完成配对确认,阻止弹窗弹出。
接收器实现代码:
public class BtPairingReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (!BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) return; // 截断广播,阻止系统弹出PIN输入框 abortBroadcast(); BluetoothDevice targetDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int pairingVariant = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR); try { switch (pairingVariant) { // Just Works标准配对类型,直接确认即可 case BluetoothDevice.PAIRING_VARIANT_CONSENT: case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION: targetDevice.setPairingConfirmation(true); break; // 部分无PIN设备会上报PIN请求类型,传入默认0值即可完成配对 case BluetoothDevice.PAIRING_VARIANT_PIN: byte[] defaultPin = {0, 0, 0, 0}; targetDevice.setPin(defaultPin); break; } } catch (SecurityException e) { // 捕获未授予BLUETOOTH_CONNECT权限的异常 e.printStackTrace(); } } }
接收器注册代码,必须设置高优先级:
IntentFilter pairFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST); // 优先级设置为仅低于系统最高优先级,优先于系统配对弹窗接收广播 pairFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1); registerReceiver(new BtPairingReceiver(), pairFilter);
3. 正常发起连接
广播注册完成、权限校验通过后,直接调用标准device.connectGatt()方法发起GATT连接即可,不需要额外调用配对接口。系统触发配对流程时会被自定义接收器拦截,自动完成无PIN配对,不会弹出PIN输入对话框。
兼容性说明
- 该方案同时适配BLE低功耗蓝牙和经典蓝牙设备,不需要反射修改蓝牙栈隐藏的IO能力配置,在主流厂商ROM上兼容性远高于反射方案
- 部分深度定制ROM会修改配对广播分发逻辑,如果遇到拦截失效的情况,可以在调用
connectGatt()前先调用device.createBond()主动发起配对流程,再配合广播接收器处理请求即可 - 不要尝试传入空PIN值,系统蓝牙栈校验逻辑不接受空PIN,传入默认全0字节数组是无PIN设备的标准配对参数
- 配对处理逻辑必须直接在
onReceive方法中同步执行,不要放到子线程或延迟执行,否则会因为广播超时导致配对失败
内容的提问来源于stack exchange,提问作者ilkeraktuna
相关产品推荐
相关产品推荐

