Android上的蓝牙低功耗专用与公共地址

Veg*_*und 24 android bluetooth-lowenergy android-bluetooth

蓝牙低功耗设备由其地址唯一标识(在Android API中,他们将其称为MAC地址,并将其表示为冒号分隔的十六进制值,例如11:aa:22:bb:33:cc).

但要唯一识别BLE地址,您需要知道它是公共地址还是私人地址.本质上,识别地址需要49位,而不是48位.

随机地址可以是静态随机地址,不可解析私有地址或可解析私有地址,这些类型在两个最高有效字节(分别为11,00和10)中由位模式分隔.

但是我没有看到只要通过查看地址中的48位就可以将公共地址和随机地址分开的任何地方.

那么这在Android API中如何运作?当他们不知道您指定的地址是公开的还是随机的时,他们如何知道要连接的设备?

有问题的API例如是getRemoteDevice函数.它说:

Valid Bluetooth hardware addresses must be upper case, in a format such as
"00:11:22:33:AA:BB". The helper checkBluetoothAddress(String) is available
to validate a Bluetooth address.

A BluetoothDevice will always be returned for a valid hardware address,
even if this adapter has never seen that device.
Run Code Online (Sandbox Code Playgroud)

所以你给函数48位数据,没有办法告诉它地址是公共的还是私有的.这意味着设备未被唯一标识.

Veg*_*und 11

由于没有其他人似乎有答案,我开始自己测试.

我尝试制作一个应用程序,从地址的字符串表示创建一个设备,并尝试使用48位地址设置我的设备交替公共或私有位,以查看Android堆栈的作用.

private final BluetoothGattCallback leGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            Log.i("Fisken", "Gatt connected " + gatt.getDevice().getAddress() + " status " + status);
            if (status != BluetoothGatt.GATT_SUCCESS) {
                Log.w("Fisken", "Disconnect and close");
                gatt.disconnect();
                gatt.close();
            }
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            Log.i("Fisken", "Gatt disconnected " + gatt.getDevice().getAddress() + " status " + status);
            if (status != BluetoothGatt.GATT_SUCCESS) {
                Log.w("Fisken", "Disconnect and close");
                gatt.disconnect();
            }
            gatt.close();
        }
    }
};

BluetoothAdapter mBluetoothAdapter = ((BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
BluetoothDevice d = mBluetoothAdapter.getRemoteDevice("FF:55:44:33:22:11");
d.connectGatt(this, false, leGattCallback);
Run Code Online (Sandbox Code Playgroud)

使用此代码,如果我使用随机地址启动我的BLE外设,一切都按预期工作.但是,如果我尝试使用公共位设置的相同地址运行它,则logcat会说"Gatt connected",但事实并非如此.我永远无法断开连接.

更新:我做了一些测试来解决这个问题.我得到的onConnectionStateChange事件只是连接尝试超时.状态设置为133(如果我得到STATE_CONNECTED)或257(如果我得到STATE_DISCONNECTED)并且我已经看到了两者.在任何一种情况下,我都应该(现在在示例代码中)取消连接尝试并关闭客户端.

我还发现,如果我先进行扫描,那么我最近已经看到了我正在尝试连接的设备然后根据设备的mac地址进行连接,那么我就可以连接到两个随机和公共地址没有任何麻烦.

所以这似乎是Android API中的错误/和缺失功能.它不允许您在未先扫描的情况下连接到公共地址.然而,它确实适用于随机地址.