Android 蓝牙低功耗配对

Posted

技术标签:

【中文标题】Android 蓝牙低功耗配对【英文标题】:Android Bluetooth Low Energy Pairing 【发布时间】:2013-08-14 09:09:32 【问题描述】:

如何将 蓝牙低功耗 (BLE) 设备与 android 配对以读取加密数据。

使用Android BLE page 中的信息,我能够发现设备、连接到它、发现服务并读取未加密的特征。

当我尝试读取加密特征(会导致 ios 显示要求配对然后完成读取的弹出窗口)时,我收到 错误代码 5,对应于 @987654322 @。

我不确定如何使设备配对或如何提供身份验证信息以完成读取

我通过尝试添加描述符来玩弄 BluetoothGattCharacteristics,但这也不起作用。 任何帮助表示赞赏!

【问题讨论】:

这方面有什么更新吗?我也面临同样的问题。 我还没有找到解决方案。我确实知道,如果您将 connectGatt 函数中的自动连接标志设置为 true,您会发现该设备显示在配对列表中,但由于其他连接错误,我无法测试并查看这是否真的允许加密。 @Zomb- 我正在尝试扫描 BLE 设备但未能实现它。如果您知道如何扫描 BLE 设备,请提供帮助。 【参考方案1】:

当您收到 GATT_INSUFFICIENT_AUTHENTICATION 错误时,系统会为您启动绑定过程。在下面的示例中,我尝试在血糖监测仪上启用通知和指示。首先,我启用了可能导致错误出现的葡萄糖测量特性的通知。

@Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) 
        if (status == BluetoothGatt.GATT_SUCCESS) 
            if (GM_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid())) 
                mCallbacks.onGlucoseMeasurementNotificationEnabled();

                if (mGlucoseMeasurementContextCharacteristic != null) 
                    enableGlucoseMeasurementContextNotification(gatt);
                 else 
                    enableRecordAccessControlPointIndication(gatt);
                
            

            if (GM_CONTEXT_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid())) 
                mCallbacks.onGlucoseMeasurementContextNotificationEnabled();
                enableRecordAccessControlPointIndication(gatt);
            

            if (RACP_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid())) 
                mCallbacks.onRecordAccessControlPointIndicationsEnabled();
            
         else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) 
            // this is where the tricky part comes

            if (gatt.getDevice().getBondState() == BluetoothDevice.BOND_NONE) 
                mCallbacks.onBondingRequired();

                // I'm starting the Broadcast Receiver that will listen for bonding process changes

                final IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
                mContext.registerReceiver(mBondingBroadcastReceiver, filter);
             else 
                // this situation happens when you try to connect for the second time to already bonded device
                // it should never happen, in my opinion
                Logger.e(TAG, "The phone is trying to read from paired device without encryption. Android Bug?");
                // I don't know what to do here
                // This error was found on Nexus 7 with KRT16S build of Andorid 4.4. It does not appear on Samsung S4 with Andorid 4.3.
            
         else 
            mCallbacks.onError(ERROR_WRITE_DESCRIPTOR, status);
        
    ;

mBondingBroadcastReceiver 在哪里:

private BroadcastReceiver mBondingBroadcastReceiver = new BroadcastReceiver() 
    @Override
    public void onReceive(final Context context, final Intent intent) 
        final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
        final int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);

        Logger.d(TAG, "Bond state changed for: " + device.getAddress() + " new state: " + bondState + " previous: " + previousBondState);

        // skip other devices
        if (!device.getAddress().equals(mBluetoothGatt.getDevice().getAddress()))
            return;

        if (bondState == BluetoothDevice.BOND_BONDED) 
            // Continue to do what you've started before
            enableGlucoseMeasurementNotification(mBluetoothGatt);

            mContext.unregisterReceiver(this);
            mCallbacks.onBonded();
        
    
;

记得在退出活动时取消注册广播接收器。它可能没有被接收者自己注销。

【讨论】:

是的,它已在 Android 4.4.1 的 Nexuses 上修复。现在错误 NO 5(身份验证不足)根本没有出现,因此您必须更早注册绑定广播侦听器(f.r 在调用 connectGatt(..) 之前。在这里您可以找到更多错误编号:android.googlesource.com/platform/external/bluetooth/bluedroid/… 什么是 mCallbacks?是否有 onBonded() 的实现?另外,mContext?这只是 getApplicationContext() 吗? yup @philips77 我也收到此错误。设备在第二次连接时已经绑定,同时写入描述符值可以解决这个问题吗?仅当我使用 kitkat 中可用的 createBond() 方法时才会发生这种情况,这很牛逼。 I'm getting gatt error 15 (GATT_INSUFFICIENT_ENCRYPTION) 在三星 S4 (4.4.2) 上尝试读取特性。那是什么? 表示设备需要绑定(加密传输)。通常片刻之后手机会自动绑定到设备上,或者您可以在连接后(例如在服务发现之前)在 Android 4.4+ 上调用 createBond()。【参考方案2】:

您可能需要检查内核 smp.c 文件,它调用了哪种配对方法进行配对。 1) 密码 2) 只是工作等。我想如果它能够调用 MIMT 和密钥级别的安全性,就不会有任何身份验证问题。确保所有标志都设置为调用 SMP 密钥方法。通过在 smp.c 文件中放置一些打印来跟踪。

适用于 ICS 的解决方案:在 android 中使用 btmgmt 工具并将其挂接到加密 API 中。使用密码或任何其他方法。有用。您可能需要使用最新的 bluez 代码在 btmgmt 中添加密码 API。

【讨论】:

我不确定我是否理解这一点。您是在谈论在 Android 端还是 BLE 设备端启用加密?因为初学者的 Android 使用 bluedroid 而不是 bluez 用于 BLE。我希望避免更改内核并重新编译 Android 以检测如何启用加密。 这里有一些检查点,您需要确保,1) 验证您的 android 设备是否支持 BLE 安全性,例如。设置加密和设置密码或OOB或只是工作。如果它支持密钥,一切皆有可能。在这种情况下,您需要输入 BLE 传感器上提到的正确密码,为此您将在 android 上弹出一个输入密码。 2) 内核端,你不想改变,应该启用安全性,让我知道你使用的是哪个内核版本? @RobinSingh 如何从 android 端执行 OOB。任何示例代码【参考方案3】:

我认为新的 android 4.4 提供了配对方法。我已经面临同样的问题,所以等待更新并希望通过 createBond() 方法解决问题。

http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#setPairingConfirmation%28boolean%29

【讨论】:

以上是关于Android 蓝牙低功耗配对的主要内容,如果未能解决你的问题,请参考以下文章

Android 蓝牙开发 -- 低功耗蓝牙开发

低功耗蓝牙配对绑定解读和实践

深入理解低功耗蓝牙的配对过程- Part 3 LE legacy Pairing Passkey Entry

如何在 Windows 桌面应用程序中配对和搜索手机上的蓝牙低功耗服务?

适用于Android的蓝牙低功耗(BLE)外设应用程序

Android 低功耗蓝牙(Ble) 开发总结