Ошибка Bluetooth SPP - конкуренция с другими BroadcastReceivers? - PullRequest
0 голосов
/ 15 апреля 2011

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

Справочная информация об устройстве: устройство представляет собой сканер штрих-кода, действующий в качестве сервера Bluetooth,используя SPP через RFCOMM.Он всегда инициирует соединение и будет отклонять входящие соединения.После подключения он загрузит данные, а затем будет ждать подтверждения.Если ACK получен, то та же передача не будет повторена.Если в течение (относительно короткого) периода ожидания ACK не получен, то передача будет постоянно повторяться.Устройство знает, куда отправляются данные, потому что оно сканирует штрих-код, который содержит BDA устройства, которое будет принимать передачу.Сканер никогда не может быть обнаружен и никогда не сканирует устройства.

Когда выполняется передача, и приложение не запущено, Android на планшете отображает тост: «Удаленное устройство пытается получить доступ к вашему телефону.панель уведомлений. "

Что мне нужно и что работает до этого момента: По сути, мне нужно принять входящие данные со сканера, а затем ответить с подтверждением.Поскольку это конкретное приложение для конкретного устройства, автоматическое сопряжение было в моем списке пожеланий.(Устройство всегда использует «0000» в качестве PIN-кода).

У меня есть планшет Samsung Galaxy для разработки, хотя я также тестировал Nexus One (HTC Passion) и телефон Samsung Galaxy Vibrant.

Я начал с примера чата Bluetooth и просмотрел множество вопросов Stackoverflow в своих путешествиях.Со временем вот что произошло:

1: я начал с базового метода «createRfcomm ... ()», используя стандартный SPP UUID, а затем добавил «connect ()».Хотя были некоторые проблемы с синхронизацией, я смог полу-надежно создать соединение, получить потоки чтения и записи, получить данные и отправить подтверждение.

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

2: Я обнаружил BroadcastReceiver для ACL_CONNECT.Я зарегистрировал это во время моего OnResume (), и вещи изменились значительно.Кроме того, я зарегистрировал «PAIRING_REQUEST» для управления автоматическим сопряжением, даже если он не поддерживается напрямую API 2.0+.

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

Итак - попытка подключения приходит, и если она не сопряжена, PAIRING_REQUESTдействие признается.Благодаря использованию функций «createBond», «setPin» и «setPairingConfirmation» все мое отражение теперь автоматически сопряжено.Он работает без проблем на двух мобильных телефонах.Однако на планшете время от времени появляется диалоговое окно ввода PIN-кода на долю секунды, прежде чем оно исчезнет.В любом случае автоматическое сопряжение всегда работает.

Важно отметить, что даже когда мое приложение работает, появляется системное уведомление "Удаленное устройство пытается получить доступ к вашему телефону ...".

После завершения сопряжения, будь то во время предыдущей или текущей передачи, оно перемещается в connect ().Первая проблема заключается в следующем:

Более 99% времени первая попытка подключения () истекает (приблизительно 12 секунд).Сразу после сбоя я снова пытаюсь подключиться (), и большую часть времени он работает.Иногда требуется еще несколько попыток, а иногда и безуспешно, но обычно это работает после нескольких повторных попыток.

Интересно, удастся ли это или нет, но Android ответит тостом: «Невозможно соединиться сУстройство Bluetooth ".Это на самом деле не имеет смысла для меня, потому что устройство сопряжено, и единственное, что выходит из строя, - это то, что система (по умолчанию BroadcastReceiver?) Не устанавливает соединение.

В этот момент у меня возник вопрос - почему первый connect () всегда терпит неудачу? Это имеет отношение к уведомлению и возможному отказу? Могу ли я переопределить это? Или мне чего-то не хватает?

Следующим, что я попробовал, была установка приоритета и прерывание трансляции, но я понял, что трансляция Bluetooth не была заказана. Без кубиков.

Что я действительно хотел бы знать, это:

A: Могу ли я поручить Android игнорировать эту попытку входящего соединения и разрешить приложению обработать ее?

B: В качестве альтернативы, могу ли я заставить систему прервать все, что она делает (возможно, блокирует канал?), А затем позволить мне попробовать свой собственный метод connect ()? Как минимум, он не должен просто продолжать работать до тех пор, пока не появится сообщение «Невозможно подключить устройство Bluetooth» для устройства, которое уже сопряжено.

C: Есть ли способ просто "открыть COM-порт", а затем иметь дело с соединениями, как они происходят? Проще говоря - можно ли просто получить открытый порт с необработанным потоком?

Д: Есть ли что-нибудь еще, что кто-то думает, что я скучаю?

Дополнительная информация:

На Nexus проблем нет. Он работает последовательно, каждый раз, без каких-либо задержек. Это работает 2.3.3. Это очень сильно отличается от этого:

Проблема в соединении Bluetooth через SPP в Android 2.3.3 в Nexus One?

Самсунг Vibrant худший - большинство соединений не удается. Это работает 2.2. Планшет также работает под управлением 2.2, и, как я уже говорил, большинство подключений работает после нескольких выходов на пенсию.

Буду очень признателен за любые предложения о том, как я могу заняться тем, что я считаю соревнованием за трансляцию Для полноты, с помощью connect () следует код:

    try
{
    // Make sure that there is no discovery going on
    btAdapter.cancelDiscovery();

    // Attempt to create the socket
    btSocket = currentBtDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
    btDebugStage = DEBUG_STAGE_HAS_SOCKET;
}
catch (IOException e)
{
    e.printStackTrace();
    return;
}

try
{
    // Attempt to connect to the Bluetooth device
    btDebugStage = DEBUG_STAGE_ATTEMPT_CONNECT;
    btSocket.connect();

    btDebugStage = DEBUG_STAGE_CONNECTED;
    btConnected = true;
}
catch (IOException e)
{
    try
    {
        btSocket.close();
    }
    catch (IOException e2)
    {
        Log.e(TAG, "Unable to close() socket after connection failure", e2);
    }

    // If it doesn't connect then make a note of it
    btConnected = false;
}

1 Ответ

1 голос
/ 27 октября 2011

В Android Bluetooth все еще могут быть некоторые глюки, однако в этом случае вы писали об удаленном BT-устройстве:

Он всегда инициирует соединение и будет отклонять входящие соединения.

В своем фрагменте кода вы попробуете только то, что не должно работать: Инициируйте соединение с устройства Android до удаленного устройства.

Теперь я обнаруживаю входящие попытки подключения и затем запускаю connect ()

Это почти наверняка совершенно неправильный подход - и, фактически, он должен не работать вообще.Если на некоторых устройствах это происходит с перебоями, то это скорее ошибка на этих устройствах, чем недокументированная функция.

Так, при работе с входящими Bluetooth-соединениями на Android, используйте подход сервера прослушивания, описанныйНапример, в:

http://developer.android.com/guide/topics/wireless/bluetooth.html#ConnectingAsAServer

с использованием listenUsingRfcommWithServiceRecord () .

Что касается сопряжения на устройствах Android: сопряжение необходимо выполнить только один раз длякаждое удаленное устройство.После сопряжения устройства Android сохраняет информацию о сопряжении и разрешает будущие подключения без запроса PIN-кода для повторного сопряжения.

...