android - Android 上低功耗蓝牙中的私有(private)地址与公共(public)地址

标签 android bluetooth-lowenergy android-bluetooth

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

但要唯一标识 BLE 地址,您需要知道它是公共(public)地址还是私有(private)地址。本质上,识别地址需要 49 位,而不是 48 位。

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

但我看不到任何地方可以仅通过查看地址中的 48 位来区分公共(public)地址和随机地址。

那么这在 Android API 中是如何工作的呢?当他们不知道您指定的地址是公共(public)地址还是随机地址时,他们怎么知道要连接什么设备?

有问题的 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.

所以你给函数 48 位数据,没有办法告诉它地址是公共(public)的还是私有(private)的。这意味着该设备没有唯一标识。

最佳答案

由于似乎没有其他人可以提供答案,我开始自己进行测试。

我尝试制作一个从地址的字符串表示形式创 build 备的应用,并尝试使用 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);

使用此代码,如果我使用随机地址启动 BLE 外围设备,一切都会按预期工作。但是,如果我尝试使用设置了公共(public)位的相同地址运行它,logcat 会显示“Gatt connected”,但事实并非如此。而且我永远无法断开连接。

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

我还发现,如果我先进行扫描,那么我尝试连接的设备最近已被看到,然后仅基于设备 mac 进行连接address 然后我可以毫无问题地连接到随机地址和公共(public)地址。

所以这似乎是 Android API 中的一个错误/和/或缺失功能。它不允许您在没有先扫描公共(public)地址的情况下连接到公共(public)地址。但它确实适用于随机地址。

关于android - Android 上低功耗蓝牙中的私有(private)地址与公共(public)地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23471364/

相关文章:

ios - 核心蓝牙 : detect device out of range/connection timeout

android - 使用不同版本的 Android 设备进行扫描时,为同一 BLE 设备获取不同的 byte[] scanRecord 数据

xamarin.forms - Xamarin跨平台蓝牙连接的示例代码

java - 安卓 : Update data on car audio

android - 如何增加 Android 中的蓝牙配对窗口超时

android - 如何在简单适配器的 ImageView 中显示图像?

android - Meteor APK 构建与 accounts-google 中断

Android Logcat 垃圾邮件很多

java - 在 Java 中获取特定时间段后的日期

android - 如何使用 Android 连接蓝牙打印机?