Android蓝牙经典模式下获取VID/PID遇connectGatt错误133求助
问题
我正在开发一款获取蓝牙设备厂商ID(VID)和产品ID(PID)的应用,该应用在BLE设备上运行正常,但连接仅支持经典模式(BR/EDR)的设备时出现错误状态133。请问如何通过connectGatt连接经典模式设备?
相关代码片段如下:
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { Log.d(TAG, "### onConnectionStateChange status: " + status + ", state: " + newState); } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { final UUID SERVICE_DEVICE_INFORMATION = UUID.fromString("0000180a-0000-1000-8000-00805f9b34fb"); List<BluetoothGattService> svclist = gatt.getServices(); if (svc.getUuid().equals(SERVICE_DEVICE_INFORMATION)) { List<BluetoothGattCharacteristic> characteristics = svc.getCharacteristics(); } } @Override public void onCharacteristicRead( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { byte[] value = characteristic.getValue(); Log.d(TAG, "### onCharacteristicRead: UUID: " + characteristic.getUuid().toString()); if (value != null && value.length == 7) { Log.d( TAG, String.format( "### vid:%x pid:%x version:%x", (0xFF & value[1]) | (0xFF & value[2]) << 8, (0xFF & value[3]) | (0xFF & value[4]) << 8, (0xFF & value[5]) | (0xFF & value[6]) << 8)); } } }; device.connectGatt(context, true, bluetoothGattCallback, device.getType());
我尝试过使用fetchUuidsWithSdp并添加ACTION_UUID的处理逻辑,虽然获取到了HID UUID(00001124-0000-1000-8000-00805f9b34fb),但未得到除BASE_UUID和HID UUID之外的其他信息。
我还尝试了device.sdpSearch(BluetoothUuid.Hid),并在ACTION_SDP_RECORD中查看SDP记录,但没有收获,相关日志如下:
Debug: android.bluetooth.device.extra.SDP_SEARCH_STATUS = "0" Debug: android.bluetooth.device.extra.DEVICE = "F4:73:35:06:74:3E" Debug: android.bluetooth.device.extra.SDP_RECORD = "BluetoothSdpRecord [rawData=[], rawSize=0]" Debug: android.bluetooth.device.extra.UUID = "00001124-0000-1000-8000-00805f9b34fb"
解决方案
1. 明确connectGatt的局限性
BluetoothGatt是专为BLE设备设计的API,无法直接连接仅支持经典蓝牙(BR/EDR)的设备,这是出现错误133的核心原因。经典蓝牙设备需要使用传统的RFCOMM连接方式,而非Gatt协议。
2. 获取经典蓝牙设备VID/PID的正确路径
经典蓝牙设备的VID和PID通常存储在SDP记录的Device ID服务中,需通过以下步骤获取:
- 确保设备已与手机完成配对
- 搜索SDP中的Device ID服务(UUID:
00001200-0000-1000-8000-00805f9b34fb) - 解析该服务的属性提取VID、PID
3. 代码调整示例
步骤1:注册广播接收器监听SDP搜索结果
private BroadcastReceiver sdpReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_SDP_RECORD.equals(action)) { int status = intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1); if (status == BluetoothDevice.SDP_SUCCESS) { BluetoothSdpRecord record = intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD); if (record != null) { parseDeviceIdSdpRecord(record); } } } } }; // 在Activity/Fragment的onCreate中注册接收器 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_SDP_RECORD); registerReceiver(sdpReceiver, filter);
步骤2:发起Device ID服务的SDP搜索
// 先检查设备配对状态 if (device.getBondState() == BluetoothDevice.BOND_BONDED) { UUID deviceIdServiceUuid = UUID.fromString("00001200-0000-1000-8000-00805f9b34fb"); device.sdpSearch(deviceIdServiceUuid); }
步骤3:解析SDP记录提取VID/PID
private void parseDeviceIdSdpRecord(BluetoothSdpRecord record) { // 获取Device ID服务的核心属性(属性ID 0x0003) BluetoothSdpAttribute attr = record.getAttribute(0x0003); if (attr != null) { byte[] data = attr.getValue(); if (data != null && data.length >= 8) { // 按Device ID服务格式解析:偏移2-3字节为VID,4-5字节为PID int vid = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF); int pid = ((data[4] & 0xFF) << 8) | (data[5] & 0xFF); Log.d(TAG, "经典蓝牙设备 VID: " + String.format("%04X", vid) + ", PID: " + String.format("%04X", pid)); } } }
4. 特殊设备的备选方案
部分HID设备(如键盘、鼠标)可能不暴露Device ID服务,可尝试读取系统存储的配对元数据:
Bundle metadata = device.getMetadata(BluetoothDevice.METADATA_GATT); if (metadata != null) { int vid = metadata.getInt(BluetoothDevice.EXTRA_VENDOR_ID); int pid = metadata.getInt(BluetoothDevice.EXTRA_PRODUCT_ID); // 使用获取到的VID/PID }
内容的提问来源于stack exchange,提问作者Lance Bai
相关产品推荐
相关产品推荐

