IOException: Lesen ist fehlgeschlagen, sockel könnte geschlossen - Bluetooth auf 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?
Ich habe versucht, die obige Lösung , kann sombody Hilfe auf dieses Problem stackoverflow.com/q/52105647/1559331
InformationsquelleAutor 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.
+1. Vielen Dank!! 🙂
Wow!!! tolle Lösung!
Sorry zu sagen, aber auch deine Lösung mit dem fallback hat nicht mein problem Gelöst. Immer folgende Fehlermeldung.
Fallback failed. Cancelling. java.io.IOException: Connection refused
Bitte helfen.Noch immer Fehler..... Bitte helft mir ich habe, um die Arbeit........... Kannst du mir ein Stück code, wie Sie mit dieser Klasse. Es wird wirklich helfen, für andere............. Fallback gescheitert. Abbrechen.java.io.IOException: Lesen ist fehlgeschlagen, sockel könnte geschlossen oder timeout, Lesen ret: -1 ............... java.io.IOException: could not connect to device: 00:0E:0B:10:39:1E
InformationsquelleAutor 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):
vielen Dank George für die Einblicke in die
mPort
parameter! imho der workflow bleibt der gleiche, nur ich wickelte Dinge mit einigen Klassen implementieren eine Schnittstelle.ja, ich habe bereits gesagt, deine Lösung war gut, aber ich wollte die Menschen verstehen, warum es braucht, um diesen Ansatz beginnend mit android 4.2
SPP = Serial Port profile " (Profil emuliert eine serielle Schnittstelle über bluetooth) und ELM327 ist ein bluetooth <-> obd KFZ Gerät , google es.
Seine arbeitete für mich nach geändert, der port-Wert von 1 bis 2.betrachten Sie bitte diesen code. socket =(BluetoothSocket) Gerät.getClass().getMethod("createRfcommSocket", neue Klasse[] {int.class}).invoke(device,2); socket.connect();
InformationsquelleAutor 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.
mich töten , nur, dass Tipp! ich habe einmal gelesen, aber ignorieren, dass
InformationsquelleAutor tobiasBora
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.
habe versucht, alle der obigen Szenarien , (außer für das entfernen von anderen angeschlossenen Geräten verursacht gut, dass ist nicht wirklich eine Lösung gefunden, ja ... das ist in der Regel nur passiert, wenn die input-streams und sockets bekommen nicht richtig geschlossen.....!!
InformationsquelleAutor Daniel T
Setzen Sie
registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID"));
mit "bluetooth" geschrieben "bleutooth".
InformationsquelleAutor Fizz Binn
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 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 kmac.mcfarlane
Falls jemand Probleme hat mit Kotlin, hatte ich zu Folgen, die akzeptierte Antwort mit einigen Variationen:
Hoffe es hilft
InformationsquelleAutor Santiago Martí Olbrich
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 ireshika piyumalie
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 kmac.mcfarlane
Sogar ich hatte das gleiche problem ,verstehe schließlich mein Problem , ich habe versucht, schließen Sie aus (out of range) Bluetooth-Reichweite.
InformationsquelleAutor krishna murthy
Ich lief in dieses problem und es behoben durch schließen der input-und output-streams vor dem schließen des socket. Jetzt kann ich die Verbindung trennen und wieder verbinden ohne Probleme.
https://stackoverflow.com/a/3039807/5688612
In Kotlin:
InformationsquelleAutor TheoKanning
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 taotao