Pour créer une connexion entre deux appareils, vous devez implémenter à la fois les
des mécanismes côté serveur et côté client, car un appareil doit ouvrir un serveur
socket, et l'autre doit initier la connexion à l'aide de l'adresse IP
adresse MAC. Le serveur et l'appareil client obtiennent chacun l'autorisation
BluetoothSocket
dans différentes
de différentes manières. Le serveur reçoit des informations de socket lorsqu'une connexion entrante est
accepté. Le client fournit des informations de socket lorsqu'il ouvre un canal RFCOMM
sur le serveur.
Le serveur et le client sont considérés comme
connectés l'un à l'autre lorsqu'ils ont chacun
un BluetoothSocket
connecté sur le même canal RFCOMM. À ce stade, chaque
l'appareil peut obtenir des flux d'entrée et de sortie, et le transfert de données peut commencer, ce qui
est abordée dans la section concernant le transfert Bluetooth
données. Cette section
explique comment établir la connexion entre deux appareils.
Assurez-vous de disposer des autorisations Autorisations Bluetooth configurer votre application pour le Bluetooth avant lorsque vous essayez de trouver des appareils Bluetooth.
Techniques de connexion
Une technique d'implémentation consiste à préparer automatiquement chaque appareil en tant que serveur de sorte que chaque appareil ait un socket de serveur ouvert et écoutant les connexions. Dans dans ce cas, l'un ou l'autre appareil peut établir une connexion avec l'autre et devenir le client. Un appareil peut aussi héberger explicitement la connexion et ouvrir un socket serveur à la demande, et l'autre appareil lance la connexion.
Figure 1 : Boîte de dialogue d'association Bluetooth.
Se connecter en tant que serveur
Lorsque vous souhaitez connecter deux appareils, l’un doit agir en tant que serveur en tenant un
ouvert
BluetoothServerSocket
L'objectif du socket serveur est d'écouter les requêtes de connexion entrantes
et fournir un BluetoothSocket
associé une fois la requête acceptée. Lorsque
BluetoothSocket
est acquise à partir de BluetoothServerSocket
, le
BluetoothServerSocket
peut et doit être supprimé, sauf si vous le souhaitez
l'appareil pour accepter plus de connexions.
Pour configurer un socket serveur et accepter une connexion, procédez comme suit : séquence d'étapes:
Obtenez un
BluetoothServerSocket
en appelantlistenUsingRfcommWithServiceRecord(String, UUID)
Il s'agit d'un nom identifiable pour votre service, que le système écrit automatiquement dans une nouvelle entrée de base de données SDP (Service Discovery Protocol) sur l'appareil. Le nom est arbitraire. Il peut simplement correspondre au nom de votre application. L'identifiant unique universel (UUID) est également inclus dans l'entrée SDP. et constitue la base de l'accord de connexion avec l'appareil client. Cela lorsque le client tente de se connecter à ce périphérique, il conserve un UUID qui identifie de manière unique le service auquel il veut se connecter. Ces Les UUID doivent correspondre pour que la connexion soit acceptée.
Un UUID est un format normalisé de 128 bits pour un identifiant de chaîne utilisé de manière unique des informations d'identification. Un UUID permet d'identifier les informations qui doivent être est unique au sein d'un système ou d'un réseau, car la probabilité qu'un UUID soit répété est effectivement zéro. Elles sont générées de façon indépendante, d'une autorité centralisée. Dans ce cas, il permet d'identifier votre service Bluetooth de l'application. Pour obtenir un UUID à utiliser avec votre application, vous pouvez en utiliser un. parmi les nombreux
UUID
sur le Web, puis initialisez un UUID avecfromString(String)
Commencez à écouter les demandes de connexion en appelant
accept()
Il s'agit d'un appel bloquant. Elle est renvoyée lorsqu'une connexion a été acceptée ou une exception s'est produite. Une connexion n'est acceptée que lorsqu'un L'appareil distant a envoyé une demande de connexion contenant un UUID qui correspond celui enregistré avec ce socket de serveur d'écoute. En cas de succès,
accept()
renvoie unBluetoothSocket
connecté.À moins que vous ne souhaitiez accepter des connexions supplémentaires, appelez
close()
Cet appel de méthode libère le socket serveur et toutes ses ressources, mais ne ferme pas le
BluetoothSocket
connecté qui a été renvoyé paraccept()
Contrairement à TCP/IP, RFCOMM n'autorise qu'un seul client connecté par canal à la fois. Dans la plupart des cas, il est donc judicieux d'appelerclose()
sur leBluetoothServerSocket
immédiatement après avoir accepté un socket connecté.
Comme l'appel accept()
est un appel bloquant, ne l'exécutez pas dans l'instance main
thread UI de l'activité. Si vous l'exécutez dans un autre thread, votre application peut
tout en continuant à réagir
aux autres interactions des utilisateurs. Il est généralement judicieux
de faire tout le travail
qui implique un BluetoothServerSocket
ou un BluetoothSocket
dans un nouveau thread
gérés par votre application. Pour annuler un appel bloqué tel que accept()
, appelez close()
sur le BluetoothServerSocket
ou BluetoothSocket
d'un autre fil de discussion. Remarque
que toutes les méthodes d'un BluetoothServerSocket
ou d'un BluetoothSocket
sont
thread-safe.
Exemple
Voici un thread simplifié pour le composant de serveur qui accepte connexions entrantes:
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); } } }
Dans cet exemple, une seule connexion entrante est souhaitée, donc dès qu'un
la connexion est acceptée et que le BluetoothSocket
est acquis, l'application transmet
acquis BluetoothSocket
dans un thread distinct, ferme
BluetoothServerSocket
, puis sort de la boucle.
Notez que lorsque accept()
renvoie BluetoothSocket
, le socket est déjà
connectés. Vous ne devez donc pas appeler
connect()
, comme vous le faites
côté client.
La méthode manageMyConnectedSocket()
propre à l'application est conçue pour lancer
pour transférer des données, qui est abordé dans l'article sur
transfert Bluetooth
données.
En général, vous devriez fermer votre BluetoothServerSocket
dès que vous avez terminé
à l'écoute des connexions entrantes. Dans cet exemple, close()
est appelé dès que
lorsque BluetoothSocket
est acquis. Vous pouvez également mettre à disposition
dans votre fil de discussion qui peut fermer le BluetoothSocket
privé dans l'événement
que vous devez arrêter d'écouter
sur ce socket serveur.
Se connecter en tant que client
Afin d'établir une connexion avec un appareil distant qui accepte
sur un socket de serveur ouvert, vous devez d'abord obtenir un BluetoothDevice
qui représente l'appareil distant. Pour apprendre à créer un
BluetoothDevice
, consultez Trouver le Bluetooth
appareils. Vous devez
Utilisez ensuite BluetoothDevice
pour acquérir un BluetoothSocket
et lancer le
.
La procédure de base est la suivante:
À l'aide de
BluetoothDevice
, obtenez unBluetoothSocket
en appelantcreateRfcommSocketToServiceRecord(UUID)
Cette méthode initialise un objet
BluetoothSocket
qui permet au client de connectez-vous à unBluetoothDevice
. L'UUID transmis ici doit correspondre à l'UUID utilisé. par le périphérique serveur lorsqu'il a appelélistenUsingRfcommWithServiceRecord(String, UUID)
pour ouvrir sonBluetoothServerSocket
. Pour utiliser un UUID correspondant, codez en dur le la chaîne UUID dans votre application, puis la référencer à partir du serveur et le code client.Établissez la connexion en appelant
connect()
. Notez que cette méthode bloquant l'appel.Une fois qu'un client a appelé cette méthode, le système effectue une recherche SDP pour trouver l'appareil distant avec l'UUID correspondant. Si la recherche réussit et que l'appareil distant accepte la connexion, il partage le canal RFCOMM pour utiliser pendant la connexion, et la méthode
connect()
renvoie un résultat. Si la connexion échoue, ou si la méthodeconnect()
expire (au bout de 12 secondes environ), alors la méthode génère une exceptionIOException
.
Comme connect()
est un appel bloquant, vous devez toujours effectuer cette
procédure de connexion dans un thread distinct de l'activité principale (UI)
thread.
Exemple
Voici un exemple de base de thread client qui lance une connexion Bluetooth connexion:
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); } } }
Notez que dans cet extrait, cancelDiscovery()
est appelé avant la connexion
d'une tentative d'accès. Vous devez toujours appeler cancelDiscovery()
avant connect()
,
d'autant plus que cancelDiscovery()
réussit, que l'appareil
découverte est en cours. Si votre application doit déterminer si
la détection d'appareils est en cours, vous pouvez vérifier
isDiscovering()
La méthode manageMyConnectedSocket()
propre à l'application est conçue pour lancer
pour transférer des données, abordé dans la section
transférer des données Bluetooth.
Lorsque vous avez terminé d'utiliser votre BluetoothSocket
, appelez toujours close()
. Procéder à cette opération
ferme immédiatement le socket connecté et libère toutes les connexions
ressources.