Сопряжение с Android Bluetooth с низким энергопотреблением

Как связать устройство Bluetooth Low Energy (BLE) с Android для чтения зашифрованных данных.

Используя информацию на странице Android BLE, я могу обнаружить устройство, подключиться к нему, откройте для себя услуги и прочтите незашифрованные характеристики.

Когда я пытаюсь прочитать зашифрованную характеристику (которая заставит iOS показать всплывающее окно с просьбой выполнить сопряжение, а затем завершить чтение), я получаю код ошибки 5, который соответствует Недостаточная аутентификация.

Я не уверен, как связать устройство или как предоставить информацию аутентификации для завершения чтения.

Я играл с BluetoothGattCharacteristics, пытаясь добавить дескрипторы, но это тоже не сработало.
Любая помощь приветствуется!


person Zomb    schedule 12.08.2013    source источник
comment
Есть обновления по этому поводу? У меня такая же проблема.   -  person Ashwini Shahapurkar    schedule 24.09.2013
comment
Мне еще предстоит найти решение этой проблемы. Я знаю, что если вы установите для флага автоматического подключения в функции connectGatt значение true, вы обнаружите, что устройство отображается в списке пар, но из-за других ошибок подключения я не смог проверить и посмотреть, позволяет ли это на самом деле шифрование.   -  person Zomb    schedule 25.09.2013
comment
@ Zomb - Я работаю над тем же, в котором я пытаюсь сканировать устройства BLE, но не могу этого добиться. Пожалуйста, помогите, если у вас есть идеи, как сканировать устройство BLE.   -  person Rajat kumar    schedule 17.09.2014


Ответы (3)


Когда вы получаете ошибку 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();
        }
    }
};

Не забудьте отменить регистрацию широковещательного приемника при выходе из действия. Возможно, он не был отменен самим получателем.

person philips77    schedule 20.11.2013
comment
Спасибо за ответ! На Nexus 7 4.3 проблема заключается в том, что при сбое чтения из-за аутентификации не происходит обратного вызова. Он просто выводит на консоль статус 5 и умирает. Я проверю и посмотрю, смогу ли я получить намерение BondStateChanged, даже если при чтении не было обратного вызова. Я подозреваю, что мне, возможно, придется вызвать create bond (4.4 API) в начале, чтобы запустить процесс, который я попробую, когда мой Nexus 7 будет обновлен. - person Zomb; 21.11.2013
comment
Я могу подтвердить, что теперь это работает с 4.4. Когда я пытаюсь прочитать зашифрованный символ, начинается связывание и обмен ключами. Хотя я не возвращаю статус 5, я все же получаю статус 137 (не уверен, что это такое) в качестве ответа на чтение символа после завершения связывания. Затем я могу снова прочитать зашифрованный символ, чтобы получить данные. Сопряженное устройство также отображается в списке устройств Bluetooth. - person Zomb; 03.12.2013
comment
Да, исправили на Нексусах с Android 4.4.1. В настоящий момент ошибка № 5 (недостаточная аутентификация) вообще не возникает, поэтому вам нужно зарегистрировать слушателя широковещательной рассылки ранее (fr перед вызовом connectGatt (..). Здесь вы можете найти другие номера ошибок: android.googlesource.com/platform/external/bluetooth / bluedroid / - person philips77; 17.12.2013
comment
Что такое mCallbacks? Есть ли реализация onBonded ()? Кроме того, mContext? Это просто getApplicationContext ()? - person Thom; 19.12.2013
comment
yup @ philips77, я также получаю эту ошибку. устройства уже связаны при подключении во второй раз при записи значения дескриптора, может ли это обойтись? это происходит только тогда, когда я использую метод createBond (), который доступен в kitkat, серьезно, это чушь собачья. - person mcd; 17.01.2014
comment
Я получал эту ошибку при чтении характеристики без createBond (). Однако, начиная с 4.4.1, я больше не получал эту ошибку (проверено на Nexus 4,5,7). - person philips77; 24.01.2014
comment
Я получаю ошибку gatt 15 (GATT_INSUFFICIENT_ENCRYPTION) при попытке прочитать характеристику на Samsung S4 (4.4.2). Что это? - person Konstantin Konopko; 24.03.2014
comment
Это означает, что устройству требуется соединение (шифрованная передача). Обычно через несколько секунд телефон автоматически подключается к устройству, или вы можете вызвать createBond () на Android 4.4+ после подключения, например, до обнаружения службы. - person philips77; 26.03.2014
comment
Кто-нибудь знает, что делать, если вы можете добраться до ошибки недостаточной аутентификации, но связывание никогда не удается? Я запускаю createBond (), а затем получаю два обратных вызова: один с BOND_BONDING, а второй с BOND_NONE, за которым следует GATT_DISCONNECT. Похоже, BT пытается записать мою характеристику, а затем вторую с uuid со всеми нулями. Я пробовал setWriteType для всех трех и получил три разных результата, но ни один из них не увенчался успехом. (NEXUS 4, андроид 4.4) - person jnewt; 27.04.2014
comment
Что такое переменная mCallbacks? - person IgorGanapolsky; 05.04.2017
comment
Просто способ распространения информации на другой уровень (пользовательский интерфейс, сервис и т. Д.). Посмотрите текущую реализацию здесь: github.com/NordicSemiconductor/Android-nRF-Toolbox/blob/master/. Это базовый класс, который обрабатывает все события BLE и может использоваться с простым API. В этом приложении есть примеры того, как использовать его в разных профилях. - person philips77; 28.04.2017
comment
Зачем регистрировать получателя при получении GATT_INSUFFICIENT_AUTHENTICATION вместо того, чтобы дожидаться получения залога перед установкой соединения? - person User; 02.05.2019

Возможно, вам потребуется проверить файл Kernel smp.c, какой метод сопряжения он вызывает для сопряжения. 1) ключ доступа 2) просто работать или тд. Я предполагаю, что если он сможет вызвать уровень безопасности MIMT и пароля, проблем с аутентификацией не возникнет. Убедитесь, что все флаги установлены для вызова методов ключа доступа SMP. отслеживать, поместив некоторую печать в файл smp.c.

Решение, которое работает в ICS: с инструментом btmgmt в Android и подключением его к API шифрования. с ключом доступа или любыми другими способами. оно работает. Возможно, вам потребуется добавить API ключей доступа в btmgmt из последней версии кода bluez.

person RobinSingh    schedule 01.10.2013
comment
Я не уверен, что понимаю это. Вы говорите о включении шифрования на стороне Android или на стороне устройства BLE? Потому что Android для начинающих использует bluedroid, а не bluez для BLE. Я надеялся избежать внесения изменений в ядро ​​и перекомпиляции Android для определения того, как включить шифрование. - person Zomb; 02.10.2013
comment
Вот некоторая контрольная точка, в которой вы должны убедиться: 1) Убедитесь, что ваше устройство Android поддерживает безопасность BLE, например. установка шифрования и установка пароля или OOB или просто работа. Если он поддерживает пароль, возможно все. в этом случае вам нужно ввести правильный ключ доступа, как указано на датчике BLE, для чего вы получите всплывающее окно на Android, чтобы ввести ключ доступа. - person RobinSingh; 04.10.2013
comment
2) сторона ядра, которую вы не хотите менять, должна быть включена безопасность, дайте мне знать, какую версию ядра вы используете? - person RobinSingh; 04.10.2013
comment
@RobinSingh Как выполнить OOB со стороны Android. Любые образцы кодов - person Ashraf; 18.01.2017

Я думаю, что новый Android 4.4 обеспечивает метод сопряжения. такая же проблема, с которой я уже столкнулся, поэтому дождитесь обновления и надейтесь, что проблема решена методом createBond ().

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

person mcd    schedule 03.11.2013