java.io.IOException: чтение не удалось, сокет может быть закрыт или истекло время ожидания, чтение ret: -1 в версии Android 5.0.1 Lollipop

Я подключаюсь через сокет Bluetooth к устройству Bluetooth и хочу прочитать байты с устройства.

Я правильно установил соединение:

 try {
         Method m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
          temp = (BluetoothSocket) m.invoke(mmDevice, 1);
 } catch (Exception e) {
 }

Я правильно читаю байты с устройства Bluetooth.

Я получаю исключение:

java.io.IOException: чтение не удалось, сокет может быть закрыт или тайм-аут, чтение ret: -1

Из-за этого соединение прерывается, а также прекращается связь между моим устройством и устройством Bluetooth.

Эта проблема особенно актуальна для Android 5.0.1 Lollipop.

Может у кого есть обходной путь?


person Kushal    schedule 19.03.2015    source источник
comment
Почему вы используете Java Reflection для этого?   -  person Jared Burrows    schedule 19.03.2015
comment
Я использовал отражение только для подключения к устройству Bluetooth.   -  person Kushal    schedule 19.03.2015
comment
Я знаю, я вижу ваш код, я спрашиваю, почему? Почему вы не используете API, поставляемые с Android SDK?   -  person Jared Burrows    schedule 19.03.2015
comment
Очень интересно. Но это работает с отражением?   -  person Jared Burrows    schedule 19.03.2015
comment
Да, это работает, мы можем использовать объект temp в дальнейшем для вызова метода connect(), т.е. temp.connect();   -  person Kushal    schedule 19.03.2015


Ответы (4)


Используйте createRfcommSocketToServiceRecord вместо createRfcommSocket

createRfcommSocketToServiceRecord принимает переданный вами UUID и использует SDP, чтобы решить, какой радиоканал использовать для соединения. Он также проверяет, прослушивает ли сервер удаленную конечную точку с тем же UUID. Таким образом, это самый надежный способ установить соединение: он всегда будет использовать правильный канал, и если соединение будет установлено успешно, вы будете знать, что что-то на другом конце может понять ваш протокол.

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

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

Конечно, поскольку createRfcommSocket не публикуется в API, вы не можете гарантировать, что он продолжит работать в будущих версиях Android.

person madhu131313    schedule 04.05.2015
comment
Большое спасибо за вашу помощь. Есть ли какая-то конкретная проблема с createRfcommSocket и Android 5.0.1 Lollipop? Я столкнулся с этой ошибкой больше в Lollipop - person Kushal; 04.05.2015
comment
Я не уверен, но метод, который я предоставил, более надежен из-за UUID. - person madhu131313; 04.05.2015
comment
Такие функции, как createRfcommSocket..., используются только для создания сокета на стороне клиента. Тем не менее, я получаю эту проблему на стороне сервера. (Я сделал сокет с помощью serversocket). Вы знаете, как исправить это на стороне сервера? - person Fuad; 19.05.2016
comment
Из документации: Чтобы создать BluetoothSocket для подключения к известному устройству, используйте BluetoothDevice.createRfcommSocketToServiceRecord(). Затем вызовите connect(), чтобы попытаться подключиться к удаленному устройству. Этот вызов будет заблокирован до тех пор, пока соединение не будет установлено или не будет установлено соединение. Чтобы создать BluetoothSocket в качестве сервера (или хоста), см. документацию по BluetoothServerSocket. - person Fuad; 19.05.2016

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

Чтобы быть более точным, BluetoothManager возвращает значение по умолчанию -1, что является неприемлемым состоянием и, следовательно, ошибкой. Это вызовет исключение, которое можно обработать, чтобы создать запасной вариант для решения проблемы путем замены ошибки -1.

Вот ссылка, которая мне помогла:

https://github.com/don/BluetoothSerial/issues/89

Ссылка: IOException: ошибка чтения , сокет может быть закрыт - Bluetooth на Android 4.3

person Abhishek Jain    schedule 27.04.2017

У меня была похожая проблема только на Lollipop (работал на предыдущих версиях), и замена «createRfcommSocket» на «createInsecureRfcommSocket» устранила проблему.

если вы выберете официальный API, вы можете попробовать createInsecureRfcommSocketToServiceRecord, так как createRfcommSocketToServiceRecord у меня тоже не работает.

person Fredo    schedule 26.05.2015
comment
Это серия комментариев к вопросу; пожалуйста, разместите их как таковые, когда сможете. - person rfornal; 26.05.2015
comment
Даже с небезопасным методом сохраняется та же ошибка. - person madhu131313; 28.05.2015

У меня аналогичная проблема с Lollipop (в данном случае 5.0.2). Я не вижу никаких проблем при запуске Kitkat. Я использую createInsecureRfcommSocketToServiceRecord. Я попробовал некоторые из предложенных методов использования отражения, но это не помогло (я думаю, что это решение было связано со старыми версиями Android). Однако, чтобы быть ясным, то, что я вижу, обычно происходит, когда я подключаюсь к нескольким устройствам SPP (считыватель штрих-кода и плата ввода-вывода с Bluetooth-радио для мобильных сетей). Я изо всех сил пытаюсь найти решение и думаю, что его может не быть, поскольку, возможно, в Lollipop есть проблема, если вы подключаетесь к двум устройствам с одним и тем же UUID (в данном случае общий SPP).

person Will Young    schedule 02.08.2016
comment
Не добавляйте такие комментарии в качестве ответа. - person Vaibhav Bajaj; 02.08.2016