Запрос на сопряжение Bluetooth на панели уведомлений?

Всем привет!

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

Например: я инициирую свой запрос на сопряжение со встроенного устройства, а затем появляется уведомление, подобное этому:

На английском языке: запрос на сопряжение для Bluetooth

И иногда мне не нужно беспокоиться об уведомлении, мое диалоговое окно просто отображается так, как я задумал.

Открывается диалоговое окно сопряжения, и в строке состояния не было уведомления

Есть ли способ поймать это уведомление и отобразить диалоговое окно, или это ошибка в моем коде, когда я инициирую сопряжение по Bluetooth?

ИЗМЕНИТЬ:

ОБНОВЛЕНИЕ 1:

Я проверил ответ, который дал мне Рино, и на самом деле он зависит от множества вещей. Есть и другие способы прямого отображения диалогового окна. При поступлении запроса на сопряжение вызывается следующий метод. Выполняется проверка, чтобы увидеть, должно ли диалоговое окно отображаться на переднем плане (true) или как уведомление (false):

public boolean shouldShowDialogInForeground(String deviceAddress) {
    // If Bluetooth Settings is visible
    if (mForegroundActivity != null) return true;

    long currentTimeMillis = System.currentTimeMillis();
    SharedPreferences sharedPreferences = getSharedPreferences();

    // If the device was in discoverABLE mode recently
    long lastDiscoverableEndTime = sharedPreferences.getLong(
            BluetoothDiscoverableEnabler.SHARED_PREFERENCES_KEY_DISCOVERABLE_END_TIMESTAMP, 0);
    if ((lastDiscoverableEndTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND)
            > currentTimeMillis) {
        return true;
    }

    // If the device was discoverING recently
    if (mAdapter != null && mAdapter.isDiscovering()) {
        return true;
    } else if ((sharedPreferences.getLong(SHARED_PREFERENCES_KEY_DISCOVERING_TIMESTAMP, 0) +
            GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND) > currentTimeMillis) {
        return true;
    }

    // If the device was picked in the device picker recently
    if (deviceAddress != null) {
        String lastSelectedDevice = sharedPreferences.getString(
                SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE, null);

        if (deviceAddress.equals(lastSelectedDevice)) {
            long lastDeviceSelectedTime = sharedPreferences.getLong(
                    SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE_TIME, 0);
            if ((lastDeviceSelectedTime + GRACE_PERIOD_TO_SHOW_DIALOGS_IN_FOREGROUND)
                    > currentTimeMillis) {
                return true;
            }
        }
    }
    return false;
}

Это фрагмент исходного кода, и, как видите, есть способы сделать это диалоговое окно видимым:

  1. Если устройство недавно находилось в режиме обнаружения
  2. Если устройство недавно обнаруживало
  3. Если устройство недавно было выбрано в сборщике устройств
  4. Если видны настройки Bluetooth

person Mazze    schedule 25.07.2011    source источник


Ответы (3)


Согласно a комментарий, который я видел в исходном коде Android

BluetoothPairingRequest - это приемник для любого запроса на сопряжение Bluetooth. Он проверяет, отображаются ли в настоящее время настройки Bluetooth, и отображает PIN-код, ключ доступа или диалоговое окно ввода подтверждения. В противном случае он помещает уведомление в строку состояния, по которому можно щелкнуть, чтобы открыть диалоговое окно ввода сопряжения.

Так что да, в зависимости от видимости BT будет отображаться диалоговое окно / уведомление.

ninja edit: 

Это может варьироваться в зависимости от используемого оборудования.

  • Если устройство недавно находилось в режиме обнаружения
  • Если устройство недавно обнаруживало
  • Если устройство недавно было выбрано в сборщике устройств
person Reno    schedule 27.07.2011
comment
Вау, спасибо, Рино. Это действительно должно быть объяснено в dev. документы! Так что я должен поставить его вперед, я думаю, или сделать его несколько заметным, я попробую, но если вы знаете ответ, пожалуйста, не стесняйтесь поделиться им :) - person Mazze; 27.07.2011
comment
Я говорю о видимости BT, вы должны отправить намерение ACTION_REQUEST_DISCOVERABLE, чтобы запросить видимость устройства, чтобы другие устройства могли его найти. - person Reno; 27.07.2011
comment
Я действительно так и делаю, но запускаю cancelDiscovery(), когда устройство обнаруживается. По этой ссылке в разделе «Обнаружение устройств» вы можете увидеть, что следует запустить cancelDiscovery(), как только устройство будет обнаружено ... верно? - person Mazze; 27.07.2011
comment
Правда, похоже, у вас есть какая-то проблема с синхронизацией событий в вашем приложении. (т.е. когда приходит ваш запрос на сопряжение, телефон не обнаруживается.) - person Reno; 27.07.2011
comment
Собственно, встроенное устройство должно быть доступно для обнаружения, не так ли? Чтобы подключиться к устройству, мне не нужно быть видимым. Я просто ищу устройства, а затем запрашиваю подключение. ПИН-код, который я выбрал на встроенном устройстве, а затем приходит запрос ... это когда программа либо показывает диалог, либо уведомление - person Mazze; 27.07.2011

Я знаю, что эта ветка устарела, но я хотел бы добавить простой ответ для людей, у которых есть такая же проблема. Приведенный выше ответ очень хорошо объясняет, почему и что, но не показывает простого решения.

Вызов этой функции перед началом связывания выполняет свою работу:

private void feintBluetoothDeviceDiscovery() {
    BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
    btAdapter.startDiscovery();
    btAdapter.cancelDiscovery();
}

Это просто запускает открытие. Выглядит как-то глупо, но вроде работает очень хорошо.

См. Также здесь: Сопряжение Bluetooth с Android: как убедиться, что запрос на сопряжение по Bluetooth отображается в диалоговом окне на передней панели вместо уведомления?

person maze    schedule 23.01.2020

Да, ветка старая, но это немного больше, чем решение @maze.

РЕДАКТИРОВАТЬ: Я беру это добавление обратно. В своем приложении только для BTLE я обнаружил, что я не запускал startDiscovery в отведенный для него период, и поэтому решение @maze не сработало. Я думаю, единственная причина, по которой добавление сработало, заключается в том, что я пробовал свое классическое приложение и приложение BTLE только что, и время еще не истекло.

Если я хочу, чтобы всплывающее окно отображалось вместо уведомления о событии сопряжения, я должен был вызвать startDiscovery () в течение одной минуты после запроса на сопряжение. Но для этого нужно сделать еще один шаг. У меня должен быть обработчик события в BroadcastReceiver.

Я наткнулся на это, потому что написал PHG, который использует непрерывный процесс фонового поиска, который циклически проходит между startDiscovery () в течение X секунд и затем Btle Scan в течение Y секунд. Он работал с обоими устройствами classic и Btle. Я знал, что мне нужен вызов startDiscovery, но поскольку классическое обнаружение обрабатывается в BroadcastReceiver, у меня были обработчики для него.

Сейчас я пишу похожий PHG, который только выполняет BTLE. Я сохранил цикл startDiscovery () в фоновом сканере, потому что знал, что мне нужно как минимум это, чтобы получить диалог. Но я удалил обработчики в BroadcastReceiver. Единственные обработчики, которые у меня были, были для парных событий. Результат - нет диалога. Итак, я добавил следующее, хотя теперь они ничего не делают, кроме печати журнала:

    //================ CONNECT ==============================
    if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(intent.getAction()))
    {
        Log.i(TAG, "BT State Receiver signaled with connected for device " + device.getName() + " with bond state " + device.getBondState());
    }

    //================ DISCONNECT ==============================
    else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction()))
    {

        Log.i(TAG, "BT State Receiver signaled with disconnect for device " + device.getName() + " with bond state " + device.getBondState());
    }

    //================ START/STOP DISCOVERY ==============================
    else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction()))
    {
        Log.i(TAG, "BT State Receiver signaled discovery started");
    }
    else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction()))
    {
        Log.v(TAG, "BT State receiver, discovery stopped");
    }

    //================ FOUND DEVICE ==============================
    else if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
    {
            Log.v(TAG, "Device discovered: name " + device.getName() +
                    " Bond state " + device.getBondState());
    }

К сожалению, я не знаю, нужно ли мне все вышеперечисленное или только обработчик ACTION_FOUND. Полагаю, я мог бы удалить остальных по одному и посмотреть, получаю ли я диалог по-прежнему, но меня поразила полоса лени.

person Brian Reinhold    schedule 14.03.2020