Um eine Verbindung zwischen zwei Geräten herzustellen, müssen Sie die beiden
serverseitige und clientseitige Mechanismen, da ein Gerät einen Server öffnen muss
und der andere muss die Verbindung über das
MAC-Adresse Das Servergerät und das Clientgerät erhalten jeweils die erforderlichen
BluetoothSocket
in anderen
. Der Server empfängt Socket-Informationen, wenn eine eingehende Verbindung
akzeptiert. Der Client stellt Socket-Informationen bereit, wenn er einen RFCOMM-Kanal öffnet.
mit dem Server.
Der Server und der Client gelten als miteinander verbunden, wenn sie jeweils
ein verbundenes BluetoothSocket
im selben RFCOMM-Kanal. An dieser Stelle
kann das Gerät Ein- und Ausgabestreams abrufen
und die Datenübertragung kann beginnen,
wird im Abschnitt zur Übertragung von Bluetooth-Daten
Daten. Dieser Abschnitt
beschreibt, wie die Verbindung zwischen zwei Geräten hergestellt wird.
Stellen Sie sicher, dass Sie Bluetooth-Berechtigungen und Ihre App für Bluetooth einrichten, bevor Sie versuchen, Bluetooth-Geräte zu finden.
Verbindungstechniken
Eine Implementierungstechnik besteht darin, jedes Gerät automatisch als Server vorzubereiten. sodass jedes Gerät einen offenen ServerSocket hat und auf Verbindungen wartet. In In diesem Fall kann jedes Gerät eine Verbindung mit dem anderen herstellen und zum Client. Alternativ kann ein Gerät die Verbindung explizit hosten und ein und das andere Gerät initiiert die Verbindung.
Abbildung 1: Dialogfeld der Bluetooth-Kopplung
Als Server verbinden
Wenn Sie zwei Geräte verbinden möchten, muss eines davon als Server fungieren, indem ein
öffnen
BluetoothServerSocket
Der Zweck des Server-Sockets besteht darin, auf eingehende Verbindungsanfragen zu warten.
und eine verbundene BluetoothSocket
angeben, nachdem eine Anfrage angenommen wurde. Wenn der Parameter
BluetoothSocket
wird von BluetoothServerSocket
übernommen, dem
BluetoothServerSocket
kann und sollte verworfen werden, es sei denn, Sie möchten
um mehr Verbindungen zu akzeptieren.
Um einen Server-Socket einzurichten und eine Verbindung zu akzeptieren, führen Sie die folgenden Schritte aus: Abfolge der Schritte:
BluetoothServerSocket
anrufen und erhaltenlistenUsingRfcommWithServiceRecord(String, UUID)
Bei der Zeichenfolge handelt es sich um einen identifizierbaren Namen Ihres Dienstes, der vom System schreibt automatisch in einen neuen SDP-Datenbankeintrag (Service Discovery Protocol) auf dem Gerät. Der Name ist frei wählbar und kann einfach der Name Ihrer App sein. Der UUID (Universally Unique Identifier) ist ebenfalls im SDP-Eintrag enthalten und bildet die Grundlage für die Verbindungsvereinbarung mit dem Clientgerät. Das Wenn der Client versucht, eine Verbindung zu diesem Gerät herzustellen, trägt er eine UUID der den Dienst eindeutig identifiziert, mit dem eine Verbindung hergestellt werden soll. Diese Die UUIDs müssen übereinstimmen, damit die Verbindung akzeptiert wird.
Eine UUID ist ein standardisiertes 128-Bit-Format für eine String-ID, das zur Identifizierung von Informationen. Mithilfe einer UUID werden Informationen identifiziert, in einem System oder Netzwerk eindeutig, da die Wahrscheinlichkeit, effektiv Null ist. Sie werden unabhängig und ohne Verwendung einer zentralisierten Behörde. In diesem Fall werden sie zur eindeutigen Identifizierung Ihrer Bluetooth-Dienst der App. Um eine UUID für Ihre App zu erhalten, können Sie diese verwenden der vielen zufälligen
UUID
-Generatoren im Web und initialisieren dann ein UUID mitfromString(String)
Starten Sie das Warten auf Verbindungsanfragen, indem Sie Folgendes aufrufen:
accept()
Dieser Anruf wird blockiert. Sie wird zurückgegeben, wenn entweder eine Verbindung akzeptiert oder eine Ausnahme ist aufgetreten. Eine Verbindung wird nur akzeptiert, wenn ein Remote-Gerät hat eine Verbindungsanfrage mit einer UUID gesendet, die mit Der Socket, der für diesen Überwachungsserver-Socket registriert ist. Wenn der Vorgang erfolgreich war,
accept()
gibt eine verbundeneBluetoothSocket
zurück.Wenn Sie keine weiteren Verbindungen annehmen möchten, rufen Sie
close()
Dieser Methodenaufruf gibt den Server-Socket und alle zugehörigen Ressourcen frei, schließt die verbundene
BluetoothSocket
nicht, die vonaccept()
. Anders als bei TCP/IP lässt RFCOMM nur einen verbundenen Client pro in den meisten Fällen, daher ist es in den meisten Fällen sinnvoll,close()
auf derBluetoothServerSocket
sofort nach Annahme eines verbundenen Sockets.
Da der accept()
-Aufruf ein blockierender Aufruf ist, führen Sie ihn nicht im Hauptaufruf aus
Aktivitäts-UI-Thread. Durch die Ausführung in einem anderen Thread wird sichergestellt, dass Ihre Anwendung
dennoch auf andere
Nutzerinteraktionen reagieren. Normalerweise ist es sinnvoll,
mit einem BluetoothServerSocket
oder BluetoothSocket
in einem neuen Thread
die von deiner App verwaltet werden. Rufe close()
an, um einen blockierten Anruf wie accept()
abzubrechen.
zum BluetoothServerSocket
oder BluetoothSocket
aus einem anderen Thread. Hinweis
dass alle Methoden für BluetoothServerSocket
oder BluetoothSocket
Thread-sicher.
Beispiel
Im Folgenden finden Sie einen vereinfachten Thread für die Serverkomponente, die eingehende Verbindungen:
Kotlin
private inner class AcceptThread : Thread() { private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) { bluetoothAdapter?.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID) } override fun run() { // Keep listening until exception occurs or a socket is returned. var shouldLoop = true while (shouldLoop) { val socket: BluetoothSocket? = try { mmServerSocket?.accept() } catch (e: IOException) { Log.e(TAG, "Socket's accept() method failed", e) shouldLoop = false null } socket?.also { manageMyConnectedSocket(it) mmServerSocket?.close() shouldLoop = false } } } // Closes the connect socket and causes the thread to finish. fun cancel() { try { mmServerSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } }
Java
private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; public AcceptThread() { // Use a temporary object that is later assigned to mmServerSocket // because mmServerSocket is final. BluetoothServerSocket tmp = null; try { // MY_UUID is the app's UUID string, also used by the client code. tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's listen() method failed", e); } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = null; // Keep listening until exception occurs or a socket is returned. while (true) { try { socket = mmServerSocket.accept(); } catch (IOException e) { Log.e(TAG, "Socket's accept() method failed", e); break; } if (socket != null) { // A connection was accepted. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket); mmServerSocket.close(); break; } } } // Closes the connect socket and causes the thread to finish. public void cancel() { try { mmServerSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the connect socket", e); } } }
In diesem Beispiel ist nur eine eingehende Verbindung erwünscht. Wenn also
akzeptiert und die BluetoothSocket
abgerufen wird, übergibt die App den
BluetoothSocket
an einen separaten Thread übertragen, schließt den
BluetoothServerSocket
und bricht aus der Schleife ab.
Wenn accept()
den BluetoothSocket
zurückgibt, ist der Socket bereits
verbunden. Daher sollten Sie nicht
connect()
, wie Sie es tun
auf der Clientseite.
Die App-spezifische Methode manageMyConnectedSocket()
dient dazu,
Thread zum Übertragen von Daten, der im Thema
Bluetooth wird übertragen
Daten.
Normalerweise solltest du BluetoothServerSocket
schließen, sobald du fertig bist
auf eingehende Verbindungen warten. In diesem Beispiel wird close()
sofort aufgerufen
während BluetoothSocket
übernommen wird. Sie können auch eine öffentliche
in Ihrem Thread verwenden, mit der die private BluetoothSocket
im Ereignis geschlossen werden kann
dass der Server-Socket nicht mehr überwacht werden soll.
Als Kunde verbinden
Um eine Verbindung mit einem Remote-Gerät herzustellen, das diese akzeptiert
über einen offenen Server-Socket ausführen, müssen Sie zuerst einen BluetoothDevice
für das Remote-Gerät. Weitere Informationen zum Erstellen eines
BluetoothDevice
, siehe Bluetooth suchen
Geräte. Du musst
Verwenden Sie dann BluetoothDevice
, um eine BluetoothSocket
zu erhalten und den
Das grundlegende Verfahren sieht so aus:
Rufen Sie mit der
BluetoothDevice
einBluetoothSocket
ab, indem Sie Folgendes aufrufen:createRfcommSocketToServiceRecord(UUID)
Diese Methode initialisiert ein
BluetoothSocket
-Objekt, mit dem der Client Folgendes ausführen kann: eine Verbindung zu einemBluetoothDevice
herstellen. Die hier übergebene UUID muss mit der verwendeten UUID übereinstimmen vom Servergerät erstellt, wenn erlistenUsingRfcommWithServiceRecord(String, UUID)
um dieBluetoothServerSocket
zu öffnen. Um eine übereinstimmende UUID zu verwenden, hartcodieren Sie die einen UUID-String in Ihre App ein und verweisen Sie dann sowohl vom Server und Clientcode.Starten Sie die Verbindung durch Aufrufen von
connect()
. Diese Methode ist ein Anruf wird blockiert.Nachdem ein Client diese Methode aufgerufen hat, führt das System eine SDP-Suche durch, das Remote-Gerät mit der entsprechenden UUID. Wenn die Suche erfolgreich ist und der Remote-Gerät akzeptiert die Verbindung und nutzt den RFCOMM-Kanal während der Verbindung und die Methode
connect()
wird zurückgegeben. Wenn die Verbindung oder wenn bei der Methodeconnect()
eine Zeitüberschreitung auftritt (nach etwa 12 Sekunden), Die Methode löst einenIOException
aus.
Diesen Aufruf solltest du immer ausführen, da connect()
ein blockierender Aufruf ist
Verbindungsverfahren in einem Thread, der von der Hauptaktivität (UI) getrennt ist
Diskussions-Thread.
Beispiel
Im Folgenden finden Sie ein einfaches Beispiel für einen Client-Thread, der ein Bluetooth initiiert. Verbindung:
Kotlin
private inner class ConnectThread(device: BluetoothDevice) : Thread() { private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) { device.createRfcommSocketToServiceRecord(MY_UUID) } public override fun run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter?.cancelDiscovery() mmSocket?.let { socket -> // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. socket.connect() // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket) } } // Closes the client socket and causes the thread to finish. fun cancel() { try { mmSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the client socket", e) } } }
Java
private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { // Use a temporary object that is later assigned to mmSocket // because mmSocket is final. BluetoothSocket tmp = null; mmDevice = device; try { // Get a BluetoothSocket to connect with the given BluetoothDevice. // MY_UUID is the app's UUID string, also used in the server code. tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's create() method failed", e); } mmSocket = tmp; } public void run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter.cancelDiscovery(); try { // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. mmSocket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and return. try { mmSocket.close(); } catch (IOException closeException) { Log.e(TAG, "Could not close the client socket", closeException); } return; } // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(mmSocket); } // Closes the client socket and causes the thread to finish. public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the client socket", e); } } }
Beachten Sie, dass in diesem Snippet cancelDiscovery()
vor der Verbindung aufgerufen wird.
erfolgt. Rufen Sie cancelDiscovery()
immer vor dem connect()
auf.
vor allem, weil cancelDiscovery()
unabhängig davon funktioniert,
Erkennung läuft gerade. Wenn Ihre App feststellen muss,
Geräteerkennung läuft, können Sie dies mit
isDiscovering()
Die App-spezifische Methode manageMyConnectedSocket()
dient dazu,
zum Übertragen von Daten, der im Abschnitt über
Bluetooth-Daten übertragen.
Wenn du dein Gerät (BluetoothSocket
) nicht mehr nutzt, ruf immer close()
an. Vorgehensweise
Schließt den angeschlossenen Socket sofort und gibt alle zugehörigen internen
Ressourcen.