Коды ошибок в Nearby Connections 2.0

Я экспериментировал с новыми подключениями поблизости Android. v2.0 API. Большинство моих устройств теперь могут общаться друг с другом большую часть времени, но я также получаю много коды ошибок назад при попытке подключения. Проверяя status.getStatusCode() внутри своей программы, я вижу следующие коды возврата:

  • STATUS_ALREADY_CONNECTED_TO_ENDPOINT (8003)
  • STATUS_BLUETOOTH_ERROR (8007)
  • STATUS_ENDPOINT_IO_ERROR (8012)
  • STATUS_ERROR (13)

Я с трудом разбираюсь в этом. Первый код ошибки кажется очевидным, за исключением того, что я вижу его в тех случаях, когда я не нажимаю обратный вызов onConnectionResult с кодом возврата «УСПЕХ» на любой стороне предполагаемого соединения. Мой текущий код полон операторов трассировки, и я бы увидел записи в журнале, если бы эти обратные вызовы были достигнуты. Так что, возможно, устройства подключены на каком-то более низком уровне, но если это так, то код более высокого уровня не всегда об этом слышит.

Я предполагаю, что STATUS_BLUETOOTH_ERROR указывает на ошибку Bluetooth на стороне, которая ее регистрирует, а STATUS_ENDPOINT_IO_ERROR указывает на ошибку (вероятно, связанную с Bluetooth) на другом конце? Можно ли получить более подробную информацию? Статус STATUS_ERROR (13), который я вижу время от времени, звучит как код ошибки, который программист использовал бы для тех моментов «WTF, мы никогда не должны сюда попасть», но без доступа к исходному коду я могу только догадываться.

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

Я использую Nearby Connections со стратегией подключения P2P_CLUSTER. Эти проблемы чаще всего возникают, когда обе стороны занимаются как рекламой, так и открытием. Тем не менее, я написал две небольшие программы, которые специализируются либо на рекламе, либо на обнаружении, и они тоже иногда получают эти ошибки (но реже).

В сообщениях трассировки я также заметил множество предупреждающих сообщений от Nearby Connections, которые выглядят следующим образом:

09-04 22:54:40.070 3866-3924/? W/NearbyConnections: Cannot deserialize BluetoothDeviceName: expecting min 16 raw bytes, got 6

Я предполагаю, что это связано с тем, что Nearby Connections использует свои собственные короткие токены (например, ZGbx) вместо имени Bluetooth устройства? Хотя я совсем в этом не уверен. И вообще, если это собственные специальные токены Nearby Connections, то почему они выдают предупреждающие сообщения об этом?


person Rapunzel Van Winkle    schedule 04.09.2017    source источник


Ответы (2)


[Отказ от ответственности: я работаю над Nearby Connections] Я могу попытаться помочь.

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

STATUS_BLUETOOTH_ERROR: Произошла ошибка Bluetooth. Телефон скорее всего в плохом состоянии. Это (надеюсь) не должно происходить слишком часто. Но если вы действительно хотите исправить, остановите рекламу и обнаружение перед повторной попыткой requestConnection. Ближайшие подключения будут переключать Bluetooth, когда обнаружат эту ошибку, но только если больше ничего не происходит.

STATUS_ENDPOINT_IO_ERROR: Потеряно соединение с другим устройством. Это может происходить по разным причинам (могли уйти слишком далеко, глючил Bluetooth, устройство перестало отвечать и т. д.). Если вы делаете открытия, пока у вас есть связи, избегайте этого. Обнаружение может быть затруднено на телефоне и в лучшем случае снижает пропускную способность, а в худшем приводит к обрыву соединения.

STATUS_ERROR: что-то пошло не так, что не соответствовало другим кодам ошибок. Это универсально. Это чаще всего возвращается в onConnectionResult(FAILED), чтобы уведомить вас о том, что что-то пошло не так между onConnectionInitiated и ожиданием того, что обе стороны примут соединение.

Мы также понизили серьезность журнала «Невозможно десериализовать BluetoothDeviceName» в следующем выпуске, так как это на самом деле не предупреждение. Как вы сказали; ожидаемое поведение, когда мы видим устройства, не относящиеся к Nearby Connections, во время обнаружения.

Если вы продолжаете сталкиваться с проблемами, сообщите нам, какие устройства вы используете, и мы обязательно добавим их в наш набор тестов.

person Xlythe    schedule 20.09.2017
comment
Большое спасибо! В настоящее время во всем моем коде есть операторы ведения журнала, поэтому я пересмотрю свои журналы в свете этой новой информации и посмотрю, не возникнет ли закономерность. По памяти один очень распространенный шаблон — это STATUS_BLUETOOTH_ERROR, за которым немедленно (при следующей попытке) следует STATUS_ALREADY_CONNECTED_TO_ENDPOINT (без успешного нажатия onConnectionResult). Добавление задержки между попытками не помогло. Вы предлагаете мне прекращать обнаружение и/или рекламу при каждой STATUS_BLUETOOTH_ERROR? Если да, следует ли отложить перезапуск? - person Rapunzel Van Winkle; 21.09.2017
comment
Хм. Это может быть одновременный конфликт соединений; если у вас есть 2 устройства, подключающиеся друг к другу одновременно, мы (случайным образом) выведем из строя одно из устройств requestConnection() до того, как второе устройство вызовет onConnectionInititated() на обоих устройствах. Однако для этого мы используем IO_ERROR, а не BLUETOOTH_ERROR... Да, допустимым исправлением BLUETOOTH_ERROR является остановка обнаружения/объявления, а затем повторная попытка requestConnection(). - person Xlythe; 22.09.2017
comment
Нужно ли мне останавливать/запускать как рекламу, так и обнаружение, чтобы это исправить? Я изменил код, чтобы просто остановить/запустить обнаружение после ошибок Bluetooth, и это не сработало. Я думаю, что я также могу наблюдать одновременные конфликты соединений, которые, вероятно, особенно вероятны при попытке использовать новый код на двух тестовых устройствах. Я стараюсь быть осторожным: после обнаружения, когда я отправляю запрос на подключение, я игнорирую любые новые открытия и отвечаю только на запрос onConnectionInitiated, который мы запросили. (Должен ли я отвечать на эти другие?) Я пытаюсь создать простой повторяемый тестовый пример (сложный, как вы знаете). - person Rapunzel Van Winkle; 23.09.2017
comment
Остановите оба. Чем меньше это происходит, тем больше мы можем сделать, чтобы попытаться это исправить. Тем не менее, сообщите нам модель вашего телефона. Мы скорее займемся устранением первопричины, чем заставим вас прыгать через такие обручи. - person Xlythe; 25.09.2017
comment
Кроме того, для одновременных подключений мы намеренно отказываемся от одного подключения, поэтому те исключения, которые вы видите, являются ожидаемыми. Но другое соединение должно быть успешным... Если это не так, мне нужно разобраться с этим. Лучше всего продолжать пробовать эту стратегию повторных попыток (+, возможно, случайная отсрочка). - person Xlythe; 29.09.2017
comment
Вы задаете отличные вопросы, но я думаю, что они могут быть разбиты еще больше. Давайте попробуем уместить каждый вопрос/ответ в один абзац (может быть, 2, если необходимо). Как насчет... Когда возможна одновременная реклама/обнаружение? Могу ли я смешивать и сочетать стратегии? Что происходит с моими связями, когда я переключаю стратегии? Успешное подключение, за которым сразу следует отключение. Обе стороны запрашивают подключение, но соединение не устанавливается и т. д. - person Xlythe; 02.10.2017
comment
Спросите их всех :) Особенно крайние случаи, потому что их сложнее всего добавить в документацию (добавление их в документы затрудняет чтение, потому что тогда все идет со звездочкой). - person Xlythe; 03.10.2017
comment
ОШИБКА обычно означает, что соединение было разорвано между onConnectionInitiated и ожиданием принятия обеими сторонами. например. Устройства находились слишком далеко или соединение прерывалось. Это универсально для всего, кроме принятия/отклонения. Что касается последующего теста, это, вероятно, связано с тем, что Mac-адрес Bluetooth не меняется. Итак, вы увидели старую рекламу и несколько раз пытались подключиться (с несколькими внутренними попытками). Когда устройство снова начало рекламировать, Bluetooth снова стал доступным для подключения, и Discoverer с радостью подключился, а Рекламодатель с радостью согласился. - person Xlythe; 06.10.2017
comment
Ах, нет, я имел в виду, что Nearby Connections повторит внутреннюю попытку. Ниже приводится небольшая часть о том, как работает Connections. Идентификатор конечной точки отправляется как часть объявления и формирует пару id-mac-адресов на стороне Discoverer. Затем Discoverer пытается подключиться к Mac-адресу, связанному с идентификатором конечной точки. И это не удастся, потому что вы прекратили рекламу. Таким образом, он повторяет попытку, и если вы начнете размещать рекламу достаточно быстро, одна из этих попыток может быть успешной. Несмотря на то, что вы объявили другой идентификатор/имя конечной точки, адрес Mac остается прежним. - person Xlythe; 06.10.2017
comment
Я зарегистрирую ошибку, чтобы исправить это. Это блокирующая ошибка для вас? Или просто проблема с тестом? - person Xlythe; 06.10.2017
comment
Это не совсем предназначено; просто побочный эффект Bluetooth. Я зарегистрирую ошибку. Это поправимо без нарушения обратной совместимости. - person Xlythe; 06.10.2017
comment
О, спасибо за добавление новых вопросов внизу. Я пропустил несколько из них. Постараюсь ответить к вечеру понедельника. - person Xlythe; 07.10.2017
comment
Да, я определенно могу это сделать. - person Xlythe; 07.10.2017
comment
Я считаю, что ответил на все. Дайте мне знать, если есть еще вопросы (или если какой-либо из моих ответов был недостаточным). - person Xlythe; 12.10.2017
comment
Я принял этот очень полезный ответ, удалил временный раздел в конце моего вопроса и очистил здесь большую часть своих комментариев. (Я оставил свои первые пару комментариев, потому что позже я могу написать другой вопрос на их основе.) Я не помечал ни один из ваших комментариев для удаления, так как вы будете лучше судить об этом. Я думаю, что в ваших комментариях все еще есть полезная информация, которую можно было бы использовать в ваших ответах, чтобы помочь другим разработчикам? И вас интересуют дополнительные вопросы? Я планирую написать несколько! Между тем, не стесняйтесь голосовать за любой из этих вопросов, которые вы считаете интересными :) - person Rapunzel Van Winkle; 13.10.2017
comment
Я обнаружил, что STATUS_ENDPOINT_IO_ERROR возникает очень часто, когда два устройства пытаются подключиться друг к другу одновременно. В этом случае два устройства никогда не соединятся друг с другом. Следует ли мне перезапустить Discovery и Advertising на этих устройствах в надежде, что они снова успешно подключатся? Или API попытается повторно подключить устройства? - person shortstheory; 22.02.2018
comment
2 устройства, пытающиеся подключиться одновременно, являются особым случаем: ожидается, что 1 устройство выдаст ошибку, а другая сторона, как ожидается, добьется успеха. Так что IO_ERROR - ожидаемый случай, но только с одной стороны... К сожалению, радиостанции не очень хорошо справляются с одновременными соединениями и могут зависать. Внутри мы делаем некоторую случайную отсрочку и повторную попытку, но если вы получили ошибку от requestConnection(), это означает, что все наши повторные попытки не увенчались успехом. - person Xlythe; 22.02.2018
comment
Лучшее, что вы можете сделать как разработчик, это либо... (а) Перезапустить рекламу/обнаружение. В конце концов они успешно соединится. Это то, что делает образец WalkieTalkie Automatic. (b) Создайте свою собственную рандомизированную отсрочку и повторяйте вызов requestConnection() до тех пор, пока он не сработает (или пока вы не получите onConnectionInitiated с другой стороны). - person Xlythe; 22.02.2018

Я просто хочу добавить, что может быть необходимо иметь короткую строку имени клиента при вызове API.

E.g., Nearby.Connections.requestConnection(googleApiClient, shortNameHere,....)

Я генерировал свое собственное имя клиента с помощью UUID.randomUUID().toString(), и это, похоже, вызывало ошибку STATUS_BLUETOOTH_ERROR. Все, что я сделал, это изменил пример кода, чтобы использовать имя UUID и использовать P2P_CLUSTER, и я получил эту ошибку.

Это было решением для меня относительно STATUS_BLUETOOTH_ERROR.

person Markymark    schedule 14.11.2017
comment
Это интересно! Но у меня куча вопросов. Используете ли вы 4-символьную строку для своего короткого имени или какую-то другую длину? Как вы его генерируете? Это то же имя, которое вы даете, когда начинаете рекламировать или открывать для себя что-то новое? Это действительно избавило вас от всех ваших STATUS_BLUETOOTH_ERROR? Я все еще вижу это время от времени, и иногда оно доходит до состояния, когда оно никогда не выходит из него (даже после остановки/запуска рекламы и обнаружения). Я готов попробовать вашу идею, но сначала нужно лучше понять ее. - person Rapunzel Van Winkle; 14.11.2017
comment
Теперь я использую 5-символьную строку чисел, подобную той, что была в примере (просто используя класс java.util.Random). Да, я использовал/использую SharedPreferences для хранения сгенерированного идентификатора. Итак, я играл с ним еще около часа и периодически получал еще STATUS_BLUETOOTH_ERROR. Раньше я получал эту ошибку каждый раз. Это пример, о котором я говорю github.com/googlesamples/android-nearby - person Markymark; 14.11.2017
comment
Прямо сейчас я столкнулся с проблемой, когда пытаюсь отправить байты и файл, как описано здесь developers.google.com/nearby/connections/android/exchange-data, но сразу же, когда я пытаюсь отправить, соединение теряется. Я все еще расследую это. - person Markymark; 14.11.2017
comment
Ну, периодические ошибки лучше, чем ошибки каждый раз, так что я думаю, что это прогресс. В настоящее время я использую имена длиной от 17 до 31 символа (16 псевдослучайных символов, хранящихся в общих настройках, объединенных с определяемым пользователем отображаемым именем длиной от 1 до 15 символов). - person Rapunzel Van Winkle; 14.11.2017
comment
Хорошо знать. Я только что понял, что моя проблема из моего предыдущего комментария была вызвана тем, что когда я начал намерение выбрать изображение (отправить файл на другое устройство), основное действие было приостановлено. Судя по всему, все отключается, когда активность переходит в фоновый режим. Я уверен, что причина в разряде аккумулятора. Я действительно надеялся, что IntentService с уведомлением переднего плана также сможет использовать Nearby API. Хотя не уверен, что это возможно. - person Markymark; 14.11.2017
comment
Что касается ваших потерянных соединений, я, кажется, гораздо чаще получаю onEndpointLost с самыми последними сервисами Google Play. У меня был код для понижения статуса конечной точки до неизвестного и попытки повторного подключения, но, похоже, всегда получалось УЖЕ ПОДКЛЮЧЕНО обратно. Так что в настоящее время я просто регистрирую onEndpointLost и в остальном просто игнорирую его (в основном рассматривая этот обратный вызов как шум). Я не уверен, что бы я сделал в рабочем приложении! Я предпочитаю надежную обработку ошибок, но, согласно моим текущим наблюдениям, в любом случае кажется, что он просто спонтанно восстанавливается из onEndpointLost. - person Rapunzel Van Winkle; 14.11.2017