Leider habe ich ein paar Probleme mit Androids Bluetooth. Für meine Testumgebung verwende ich ein Nexus 4 mit Android 4.4.2.
Ich habe auf meinem PC eine Java-Anwendung, die bluecove verwendet, um eine SPP-Verbindung als Client herzustellen. Das Programm sucht nach einem speziellen Dienstnamen und verbindet sich mit meinem Android-Handy. Danach sendet es 72 Bytes an mein Android-Handy und wartet auf eine Antwort. Wenn Sie diese Antwort erhalten, schläft das Programm für 3 Sekunden und beginnt dann erneut.
Auf meinem Android-Handy habe ich eine Anwendung mit Hintergrund-Bluetooth-Listener, der beim Booten startet. Diese Anwendung basiert auf einer BluetoothChat Beispieldemo. Beim Empfang von Bluetooth-Daten überprüfe ich eingehende Daten und sende eine Antwort zurück.
Alles funktioniert gut. Aber nach 489 Bluetooth-Verbindungen schlägt die Android-App mit folgendem Fehler-Snippet fehl, während die PC-Java-App läuft:
%Vor%Die App hat also ein Problem mit dem ParcelFileDescriptor, der plötzlich null ist. Aber warum?
All das oben beschriebene passiert auch, wenn die Pausenzeit auf PC-Java-App geändert wird, und verschiedene Datengrößen für die Übertragung und Verwendung verschiedener Smartphones verwendet werden. Bei Verwendung der Reflektion "listenUsingRfcommWithServiceRecord" passiert das Gleiche nach 505 Übertragungen. Auch die Verwendung von Wakelock ändert nichts.
Übrigens, ich habe das gleiche Verhalten bei der Verwendung von BluetoothChat Probe.
Also, hat irgendjemand einen Hinweis, was passiert?
Aktualisierung:
BluetoothServerSocket wird nach jeder Verbindung und BluetoothSocket geschlossen, wenn der Bluetooth-Status 3 ist.
Das Problem scheint mit dem Limit von Dateideskriptoren auf Ihrem Gerät verbunden zu sein. Es gibt einen Bericht zu diesem Problem hier
Beim Erstellen eines Bluetooth-Sockets ist ein neues fd zwei neue FDs werden vom System erworben. Es sieht so aus, als würden Sie Ihre bisherigen BT-Verbindungen nicht korrekt schließen, so dass die Anzahl der verwendeten FDs stetig steigt, bis Sie das Limit erreicht haben.
Um dies zu vermeiden, müssen Sie mindestens close()
auf der BluetoothServerSocket aufrufen, die Sie vom Aufruf listenUsingRfcommWithServiceRecord()
erhalten haben, nachdem Sie die Operationen beendet haben. Sie sollten auch überprüfen, ob Sie sich an anderen Ressourcen halten, die mit der BT-Verbindung verbunden sind, und diese nach Möglichkeit freigeben.
Wie hier angefordert wurde, wird das Schließen des ParcelFileDescriptor des BluetoothServerSocket erzwungen. Vorsicht: Es kann Dinge brechen!
Sie müssen auf das Feld mSocket von BluetoothServerSocket zugreifen, um auf die zugrunde liegende BluetoothSocket zugreifen zu können. Dieser BluetoothSocket enthält den ParcelFileDescriptor im Feld mPfd. Und darauf kannst du close()
aufrufen. Da beide Felder nicht sichtbar sind, müssen Sie Reflexionen verwenden:
Dies schließt die BluetoothServerSocket . Wenn Sie nur die BluetoothSocket von der BTServerSockets-Methode accept schließen möchten, können Sie den Teil des Abrufens von mSocket weglassen, wie in Jitain Sharmas Antwort .
Mein Fix für die Frage, die ich gestellt habe:
%Vor%Also oben ist die Methode, die ich geschrieben habe, um den Dateideskriptor zu schließen, und die folgende, wenn ich diesen Code benutzt habe: Wann immer, Steckdose muss in der Nähe sein:
%Vor%Ich habe es auch mit der clearLocalSocket () -Methode versucht, die ich geschrieben habe, aber nicht für mein Problem. Also habe ich versucht den FileDescriptor zu schließen. Ich hoffe, es wird Ihnen und anderen, die sich mit dem gleichen Problem befassen, helfen.
Dies ist ein BluetoothSocket.close () - Fehler in Android 4.2 - 4.4.4 (und 4.4w & amp; L Preview) ... Intern ruft er mPfd.detachFd () auf und gibt dann nicht den zugrunde liegenden Dateideskriptor frei. Das Problem besteht darin, stattdessen mPfd.close () aufzurufen und mPfd = null zu setzen, was genau Android 5.0 auch tut.
Sie können das meistens mit den anderen hier geposteten Lösungen beheben, die mPfd.close () aufrufen und dann den BluetoothSocket.close () Ihrer Plattform aufrufen, aber ich fand, dass das nicht genug für mich war und einige seltsame Dinge passieren könnten. Ich ging ein bisschen weiter und bereinige auch zuerst mSocket und setze diese Null, dann rufe mPfd.close () auf und setze diese Null und schließlich BluetoothSocket.close (), was benötigt wird, um mSocketState zu setzen.
%Vor%Wenn Sie Bluetooth als Server in Ihrer App verwenden, bin ich auf dasselbe Problem gestoßen, außer dass mein Problem darin besteht, dass ich bei der Reflektion auf einen Dateideskriptor mPfd trete. Ich konnte die Datei mit dieser Methode schließen, hoffe, dass dies helfen kann.
Ich erhalte die Datei über eine ID / einen Index von LoaclSocket in BluetoothSocket mit ParceFileDescriptor. int mfd = 0; Feld socketField = null; LocalSocket mSocket = null;
%Vor%