IOException: Lesen fehlgeschlagen, Socket möglicherweise geschlossen - Bluetooth unter Android 4.3
Zur Zeit versuche ich zu umgehen mit einer seltsamen Ausnahme, wenn die Eröffnung eines BluetoothSocket auf meinem Nexus 7 (2012) mit Android 4.3 (Build JWR66Y, ich denke, das zweite 4.3-update). Ich habe gesehen, einige Verwandte postings (z.B. https://stackoverflow.com/questions/13648373/bluetoothsocket-connect-throwing-exception-read-failed), aber keiner scheint sich um eine Problemumgehung für dieses Problem. Auch, wie vorgeschlagen, in diesen threads, re-pairing nicht helfen, und ständig versuchen zu verbinden (durch eine blöde Schleife) hat auch keine Wirkung.
Bin ich den Umgang mit einem embedded-Gerät (noname OBD-II Fahrzeug-adapter, ähnlich http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTERSCLEAR-CHECK-ENGINE-LIGHTS-WITH-YOUR-PHONE-Oceanside.jpg). Mein Android 2.3.7 Telefon hat keine Probleme mit der Verbindung, und das Xperia von einem Kollegen (Android 4.1.2) funktioniert auch. Eine weitere Google-Nexus (ich weiß nicht, ob 'Man' oder 'S', aber nicht '4') auch nicht mit Android 4.3.
Hier ist das Snippet, den Verbindungsaufbau. Es läuft in einem eigenen Thread, erstellt innerhalb eines Service.
private class ConnectThread extends Thread {
private static final UUID EMBEDDED_BOARD_SPP = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
private BluetoothAdapter adapter;
private boolean secure;
private BluetoothDevice device;
private List<UUID> uuidCandidates;
private int candidate;
protected boolean started;
public ConnectThread(BluetoothDevice device, boolean secure) {
logger.info("initiliasing connection to device "+device.getName() +" /"+ device.getAddress());
adapter = BluetoothAdapter.getDefaultAdapter();
this.secure = secure;
this.device = device;
setName("BluetoothConnectThread");
if (!startQueryingForUUIDs()) {
this.uuidCandidates = Collections.singletonList(EMBEDDED_BOARD_SPP);
this.start();
} else{
logger.info("Using UUID discovery mechanism.");
}
/*
* it will start upon the broadcast receive otherwise
*/
}
private boolean startQueryingForUUIDs() {
Class<?> cl = BluetoothDevice.class;
Class<?>[] par = {};
Method fetchUuidsWithSdpMethod;
try {
fetchUuidsWithSdpMethod = cl.getMethod("fetchUuidsWithSdp", par);
} catch (NoSuchMethodException e) {
logger.warn(e.getMessage());
return false;
}
Object[] args = {};
try {
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
BluetoothDevice deviceExtra = intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
Parcelable[] uuidExtra = intent.getParcelableArrayExtra("android.bluetooth.device.extra.UUID");
uuidCandidates = new ArrayList<UUID>();
for (Parcelable uuid : uuidExtra) {
uuidCandidates.add(UUID.fromString(uuid.toString()));
}
synchronized (ConnectThread.this) {
if (!ConnectThread.this.started) {
ConnectThread.this.start();
ConnectThread.this.started = true;
unregisterReceiver(this);
}
}
}
};
registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID"));
registerReceiver(receiver, new IntentFilter("android.bluetooth.device.action.UUID"));
fetchUuidsWithSdpMethod.invoke(device, args);
} catch (IllegalArgumentException e) {
logger.warn(e.getMessage());
return false;
} catch (IllegalAccessException e) {
logger.warn(e.getMessage());
return false;
} catch (InvocationTargetException e) {
logger.warn(e.getMessage());
return false;
}
return true;
}
public void run() {
boolean success = false;
while (selectSocket()) {
if (bluetoothSocket == null) {
logger.warn("Socket is null! Cancelling!");
deviceDisconnected();
openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
}
//Always cancel discovery because it will slow down a connection
adapter.cancelDiscovery();
//Make a connection to the BluetoothSocket
try {
//This is a blocking call and will only return on a
//successful connection or an exception
bluetoothSocket.connect();
success = true;
break;
} catch (IOException e) {
//Close the socket
try {
shutdownSocket();
} catch (IOException e2) {
logger.warn(e2.getMessage(), e2);
}
}
}
if (success) {
deviceConnected();
} else {
deviceDisconnected();
openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
}
}
private boolean selectSocket() {
if (candidate >= uuidCandidates.size()) {
return false;
}
BluetoothSocket tmp;
UUID uuid = uuidCandidates.get(candidate++);
logger.info("Attempting to connect to SDP "+ uuid);
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
uuid);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
uuid);
}
bluetoothSocket = tmp;
return true;
} catch (IOException e) {
logger.warn(e.getMessage() ,e);
}
return false;
}
}
Den code in Ermangelung an bluetoothSocket.connect()
. Ich bin immer ein java.io.IOException: read failed, socket might closed, read ret: -1
. Dies ist der korrespondierende Quelltext auf GitHub: https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L504
Die genannte durch readInt(), aufgerufen https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L319
Einige Metadaten-Speicherabbild der verwendeten socket-führte in den folgenden Informationen. Diese sind genau das gleiche auf dem Nexus 7 und meinem 2.3.7 Telefon.
Bluetooth Device 'OBDII'
Address: 11:22:33:DD:EE:FF
Bond state: 12 (bonded)
Type: 1
Class major version: 7936
Class minor version: 7936
Class Contents: 0
Contents: 0
Habe ich einige andere OBD-II-Adapter (mehr expansives) und Sie funktionieren alle. Gibt es irgendeine chance, dass mir etwas fehlt oder könnte das ein bug in Android?
InformationsquelleAutor der Frage matthes | 2013-09-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Habe ich endlich einen workaround. Die Magie liegt verborgen unter der Kapuze des
BluetoothDevice
Klasse (siehe https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothDevice.java#L1037).Nun, wenn ich erhalten, mit Ausnahme, instanziiere ich ein fallback
BluetoothSocket
ähnlich der source-code weiter unten. Wie Sie sehen können, das aufrufen der versteckten MethodecreateRfcommSocket
Spiegelungen. Ich habe keine Ahnung, warum diese Methode ist ausgeblendet. Der source-code definiert es alspublic
obwohl...connect()
dann nicht mehr. Ich habe erlebt, ein paar Fragen noch. Im Grunde ist dies manchmal blockiert und versagt. Neustart des SPP-Gerät (Stecker aus - /einstecken) hilft in solchen Fällen. Manchmal bekomme ich auch einen anderen Pairing-Anfrage nachconnect()
auch wenn das Gerät bereits fertig verklebt.UPDATE:
hier ist eine vollständige Klasse, die auch einige geschachtelte Klassen. für eine echte Umsetzung dieser könnte gehalten werden, als getrennte Klassen.
InformationsquelleAutor der Antwort matthes
gut, ich hatte das gleiche problem mit meinem code, und es ist, weil seit android 4.2 bluetooth-stack geändert hat. also mein code läuft problemlos auf Geräten mit android < 4.2 , auf den anderen Geräten war ich immer die berühmte Ausnahme "Lesen ist fehlgeschlagen, sockel könnte geschlossen oder timeout lese-ret: -1"
Ist das problem mit der
socket.mPort
parameter. Wenn Sie Ihre Steckdose mitsocket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);
, diemPort
bekommt integer-Wert "-1", und dieser Wert scheint nicht funktioniert für android >=4.2 , so dass Sie brauchen, um es zu "1". Die schlechte Nachricht ist, dasscreateRfcommSocketToServiceRecord
akzeptiert nur die UUID als parameter und nichtmPort
also müssen wir andere Herangehensweise. Die Antwort gepostet von @matthes auch für mich gearbeitet, aber ich es vereinfacht:socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);
. Wir müssen Sie beide sockel attribs , die zweite als fallback.Also der code ist (für die Verbindung zu einem SPP auf ein ELM327 Gerät):
InformationsquelleAutor der Antwort George Dima
Zuerst, wenn Sie brauchen, um zu sprechen, um eine bluetooth-2.x Gerät, diese Dokumentation besagt, dass :
Ich glaube nicht, dass es funktionieren würde, aber nur durch den Austausch der UUID mit
00001101-0000-1000-8000-00805F9B34FB
es funktioniert. Dieser code jedoch scheint Sie behandeln das problem der SDK-version, und Sie können einfach ersetzen Sie die Funktiondevice.createRfcommSocketToServiceRecord(mMyUuid);
mittmp = createBluetoothSocket(mmDevice);
nach der Definition der folgenden Methode :Den Quellcode ist nicht von mir, sondern kommt aus diese website.
InformationsquelleAutor der Antwort tobiasBora
Setzen Sie
registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID"));
mit "bluetooth" geschrieben "bleutooth".
InformationsquelleAutor der Antwort Fizz Binn
Hatte ich die gleichen Symptome wie hier beschrieben. Ich konnte einmal verbinden zu einem bluetooth-Drucker, aber die anschließende Verbindung ist fehlgeschlagen mit "socket geschlossen", egal was ich Tat.
Fand ich es ein bisschen seltsam, dass die workarounds, die hier beschrieben werden. Nachdem er durch meinen code hatte ich vergessen zu schließen der socket - InputStream und OutputSteram und nicht beendet, die ConnectedThreads richtig.
Den ConnectedThread die ich verwende ist die gleiche wie im Beispiel hier:
http://developer.android.com/guide/topics/connectivity/bluetooth.html
Beachten Sie, dass ConnectThread und ConnectedThread sind zwei verschiedene Klassen.
Welcher Klasse beginnt die ConnectedThread muss call interrupt() und cancel() auf dem thread.
Ich fügte hinzu, mmInStream.close() und mmOutStream.schließen() in der ConnectedTread.cancel () - Methode.
Nach dem schließen der threads/streams/buchsen richtig konnte ich erstellen, neue Steckdosen, ohne jedes problem.
InformationsquelleAutor der Antwort Daniel T
Gut, ich habe tatsächlich das problem gefunden.
Den meisten Menschen, die versuchen, eine Verbindung mit
socket.Connect();
eine Ausnahme genanntJava.IO.IOException: read failed, socket might closed, read ret: -1
.In einigen Fällen kommt es auch auf Ihrem Bluetooth-Gerät, denn es gibt zwei verschiedene Arten von Bluetooth -, nämlich BLE (low energy) und Classic.
Wenn Sie überprüfen möchten, geben Sie von Ihrem Bluetooth-Gerät, hier der code:
Ich versuche schon seit Tagen das problem zu lösen, aber seit heute habe ich das problem gefunden. Die Lösung von @matthes hat leider immer noch ein paar Probleme, wie er schon sagte, aber hier ist meine Lösung.
Im moment arbeite ich in Xamarin Android, aber dies sollte auch für andere Plattformen.
LÖSUNG
Wenn es mehr als ein gekoppeltes Gerät aus, dann sollten Sie entfernen Sie die anderen angeschlossenen Geräte. So halten Sie nur die eine, die Sie eine Verbindung herstellen möchten (siehe Bild rechts).
In der linken Abbildung sehen Sie, dass ich zwei gekoppelte Geräte, nämlich "MOCUTE-032_B52-CA7E" und "Blue Easy". Das ist das Problem, aber ich habe keine Ahnung, warum das problem Auftritt. Vielleicht ist das Bluetooth-Protokoll versucht, einige Informationen zu bekommen von einem anderen Bluetooth-Gerät.
Jedoch die
socket.Connect();
Super funktioniert jetzt ohne Probleme. Also ich wollte nur zu teilen, denn dieser Fehler ist wirklich ärgerlich.Glück!
InformationsquelleAutor der Antwort Jamie
Auf neuere Versionen von Android, war ich diese Fehlermeldung, weil der adapter war noch zu entdecken, wenn ich versuchte, eine Verbindung zu der Buchse. Obwohl ich rief die cancelDiscovery Methode der Bluetooth-adapter, die ich hatte, zu warten, bis der Rückruf der BroadcastReceiver die onReceive () - Methode aufgerufen wurde mit der Aktion BluetoothAdapter.ACTION_DISCOVERY_FINISHED.
Einmal, wartete ich auf den adapter zu stoppen Entdeckung, dann der Aufruf verbinden, die auf den sockel geschafft.
InformationsquelleAutor der Antwort kmac.mcfarlane
ich auch vor diesem problem,konnte es lösen in 2 weisen , wie bereits erwähnt, mithilfe von reflektion, erstellen des Sockets
Das zweite ist,
client ist auf der Suche nach einem server mit einer bestimmten UUID und wenn dein server nicht läuft parallel zum client, dann geschieht dies.
Erstellen Sie einen server mit client-UUID und dann hören Sie zu und akzeptieren Sie den client aus der server-Seite.Wird es funktionieren.
InformationsquelleAutor der Antwort ireshika piyumalie
Falls jemand Probleme hat mit Kotlin, hatte ich zu Folgen, die akzeptierte Antwort mit einigen Variationen:
Hoffe es hilft
InformationsquelleAutor der Antwort Santiago Martí Olbrich
Bluetooth-Geräte betreiben kann, die in klassischen und LE-Modus zur gleichen Zeit. Manchmal verwenden Sie eine andere MAC-Adresse, je nachdem, auf welche Art und Weise Sie eine Verbindung herstellen. Aufruf
socket.connect()
ist mit der Bluetooth-Klassisch, so müssen Sie sicherstellen, dass das Gerät, das Sie bekam, als Sie gescannt wurde wirklich ein classic-Gerät.Ist es leicht zu filtern, nur für Classic-Geräte, allerdings:
if(BluetoothDevice.DEVICE_TYPE_LE == device.getType()){
//socket.connect()
}
Ohne diese Prüfung, ist es eine race-Bedingung, ob ein hybrid-scan bietet Ihnen das Classic-Gerät oder die BLE-Gerät zuerst. Es mag so scheinen, als zeitweiligen Unfähigkeit, zu verbinden, oder bestimmte Geräte können Verbindung zuverlässig, während andere scheinbar nie können.
InformationsquelleAutor der Antwort kmac.mcfarlane
Habe ich auch erhalten die gleichen
IOException
aber ich finde das Android-system demo: "BluetoothChat" - Projekt gearbeitet wird. Ich habe festgestellt, das problem ist die UUID.Damit ich meine ersetzen
UUID.fromString("00001001-0000-1000-8000-00805F9B34FB")
zuUUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")
und es funktioniert am Tatort,nur manchmal neu zu starten müssen Sie das Bluetooth-Gerät;InformationsquelleAutor der Antwort taotao