Я занимаюсь разработкой bluetooth для подключения к ПК. Я в основном использовал BTChatExample и изменил UUID на стандартный профиль SPP для ПК.
Попытка закрыть приложение bluetooth во время чтения блокировки, закрыв BluetoothSocket, вы оставите стек Bluetooth в непригодном для использования состоянии. Это можно устранить, отключив и включив bluetooth и перезапустив приложение. При проверке logcat вы можете увидеть, что некоторые внутренние методы не работают, оставляя открытый порт. Любая информация об этом?
Прежде всего, существуют швы, которые могут отличаться от того, как bluetooth реализован на N1 и HTC Legend/Desire с обоими 2.1, знаете ли вы что-нибудь об этом?
Подключение не на 100% надежное, иногда я получаю предупреждение ~PortSystemContext init: FAILED
. Это оставляет непригодным Bluetooth-устройство, и требуется перезапуск.
Правильно ли я полагаю, что SPP является единственным профилем, поддерживаемым для использования с API? Об этом говорят документы в BluetoothAdapter.
Мне бы хотелось обсудить проблемы с bluetooth с разработчиком и устранить эти ошибки, чтобы Android мог иметь хорошую надлежащую поддержку Bluetooth, которой он заслуживает.
Закрытие сокета в одном потоке во время чтения блокировки обязательно должно привести к тому, что чтение будет возвращено (путем выброса IOException) и не должно оставлять стек в "плохом состоянии". Это поведение на Droid и Nexus.
Я говорил прямо с оригинальным плакатом, и он наблюдал эту проблему на HTC Legend и HTC Desire. Похоже, что они неправильно реализуют API. Я поднимаю вопрос с ними.
Вы правы, что SPP/RFCOMM является единственным профилем, который предназначен для использования с API. SPP/RFCOMM получает потоковое сокет, который достаточно хорош для многих случаев использования.
В настоящее время я рекомендую разработку BT на Nexus One/Motorola Droid, которые считаются "справочными" реализациями API Bluetooth.
Могу ли я предположить, что вы не выполняете блокировку вызовов read()
, если только вы не проверили, что данные готовы к чтению, используя inputstream.available()
, который возвращает целое число, указывающее, сколько байтов ожидает во входном буфере.
long timeouttime = gettimeinseconds() + 2;
String response = "";
while (gettimeinseconds() < timeouttime) {
if (inputstream.available() > 0)
response = response + inputstream.read();
} else {
Thread.sleep(100); // sleep to slow down the while() loop.
}
}
return response;
Это просто псевдокод и его упрощение. Суть в том, что мы не выполняем блокирующие вызовы (read()
), если мы не уверены, что они вернутся немедленно без задержки.
Кроме того, я рекомендую использовать BufferedInputStream
вместо стандартного InputStream
.
Кто-нибудь может решить эту проблему?
Я пробую следующий код:
// Keep listening to the InputStream while connected
while (!isInterrupted)
{
try
{
//Clear buffer
buffer = new byte[1024];
// Read from the InputStream
if (mmInStream != null && mmInStream.available() > 0)
{
if (isInterrupted)
break;
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Act_Main.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
}
else
{
try
{
synchronized (this)
{
this.wait(100);
}
if (isInterrupted)
break;
}
catch(InterruptedException ex)
{
Log.e(TAG, "WAIT_EXCEPTION:"+ ex.getMessage());
}
}
}
catch(Exception ex)
{
Log.e(TAG, "disconnected", ex);
connectionLost();
break;
}
}
И я изменил isInterrupted
логическое значение в методе cancel()
. Вот мой метод stop()
:
/**
* Stop all threads
*/
public synchronized void stop()
{
isStop = true ;
if (D)
Log.d(TAG, "stop");
if(mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
if(mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_NONE);
}