Transférer des données Bluetooth

Après vous être connecté à un réseau Bluetooth appareil, chacun l'un d'eux est connecté BluetoothSocket Vous pouvez maintenant partagent des informations entre les appareils. À l'aide de BluetoothSocket, la requête générale la procédure de transfert des données est la suivante:

  1. Obtenez les InputStream et OutputStream qui gère les transmissions dans le socket en utilisant getInputStream() et getOutputStream() respectivement.

  2. Lire et écrire des données dans les flux à l'aide de read(byte[]) et write(byte[])

Il y a, bien entendu, des détails de mise en œuvre à prendre en compte. Vous pouvez notamment doit utiliser un thread dédié pour la lecture et l'écriture du flux. C'est important, car les méthodes read(byte[]) et write(byte[]) bloquent les appels. La méthode read(byte[]) se bloque jusqu'à ce qu'il y ait quelque chose à lire à partir du flux. La méthode write(byte[]) ne bloque généralement pas l'accès, mais Peut être bloqué pour le contrôle de flux si l'appareil distant n'appelle pas read(byte[]) rapidement, et les tampons intermédiaires sont alors pleins. Donc, vous doit dédier votre boucle principale du thread à la lecture de InputStream. Vous pouvez utiliser une méthode publique distincte dans le thread pour lancer des écritures dans OutputStream

Exemple

Voici un exemple de transfert de données entre deux appareils connectés via le Bluetooth:

Kotlin

private const val TAG = "MY_APP_DEBUG_TAG"

// Defines several constants used when transmitting messages between the
// service and the UI.
const val MESSAGE_READ: Int = 0
const val MESSAGE_WRITE: Int = 1
const val MESSAGE_TOAST: Int = 2
// ... (Add other message types here as needed.)

class MyBluetoothService(
       // handler that gets info from Bluetooth service
       private val handler: Handler) {

   private inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() {

       private val mmInStream: InputStream = mmSocket.inputStream
       private val mmOutStream: OutputStream = mmSocket.outputStream
       private val mmBuffer: ByteArray = ByteArray(1024) // mmBuffer store for the stream

       override fun run() {
           var numBytes: Int // bytes returned from read()

           // Keep listening to the InputStream until an exception occurs.
           while (true) {
               // Read from the InputStream.
               numBytes = try {
                   mmInStream.read(mmBuffer)
               } catch (e: IOException) {
                   Log.d(TAG, "Input stream was disconnected", e)
                   break
               }

               // Send the obtained bytes to the UI activity.
               val readMsg = handler.obtainMessage(
                       MESSAGE_READ, numBytes, -1,
                       mmBuffer)
               readMsg.sendToTarget()
           }
       }

       // Call this from the main activity to send data to the remote device.
       fun write(bytes: ByteArray) {
           try {
               mmOutStream.write(bytes)
           } catch (e: IOException) {
               Log.e(TAG, "Error occurred when sending data", e)

               // Send a failure message back to the activity.
               val writeErrorMsg = handler.obtainMessage(MESSAGE_TOAST)
               val bundle = Bundle().apply {
                   putString("toast", "Couldn't send data to the other device")
               }
               writeErrorMsg.data = bundle
               handler.sendMessage(writeErrorMsg)
               return
           }

           // Share the sent message with the UI activity.
           val writtenMsg = handler.obtainMessage(
                   MESSAGE_WRITE, -1, -1, mmBuffer)
           writtenMsg.sendToTarget()
       }

       // Call this method from the main activity to shut down the connection.
       fun cancel() {
           try {
               mmSocket.close()
           } catch (e: IOException) {
               Log.e(TAG, "Could not close the connect socket", e)
           }
       }
   }
}

Java

public class MyBluetoothService {
   private static final String TAG = "MY_APP_DEBUG_TAG";
   private Handler handler; // handler that gets info from Bluetooth service

   // Defines several constants used when transmitting messages between the
   // service and the UI.
   private interface MessageConstants {
       public static final int MESSAGE_READ = 0;
       public static final int MESSAGE_WRITE = 1;
       public static final int MESSAGE_TOAST = 2;

       // ... (Add other message types here as needed.)
   }

   private class ConnectedThread extends Thread {
       private final BluetoothSocket mmSocket;
       private final InputStream mmInStream;
       private final OutputStream mmOutStream;
       private byte[] mmBuffer; // mmBuffer store for the stream

       public ConnectedThread(BluetoothSocket socket) {
           mmSocket = socket;
           InputStream tmpIn = null;
           OutputStream tmpOut = null;

           // Get the input and output streams; using temp objects because
           // member streams are final.
           try {
               tmpIn = socket.getInputStream();
           } catch (IOException e) {
               Log.e(TAG, "Error occurred when creating input stream", e);
           }
           try {
               tmpOut = socket.getOutputStream();
           } catch (IOException e) {
               Log.e(TAG, "Error occurred when creating output stream", e);
           }

           mmInStream = tmpIn;
           mmOutStream = tmpOut;
       }

       public void run() {
           mmBuffer = new byte[1024];
           int numBytes; // bytes returned from read()

           // Keep listening to the InputStream until an exception occurs.
           while (true) {
               try {
                   // Read from the InputStream.
                   numBytes = mmInStream.read(mmBuffer);
                   // Send the obtained bytes to the UI activity.
                   Message readMsg = handler.obtainMessage(
                           MessageConstants.MESSAGE_READ, numBytes, -1,
                           mmBuffer);
                   readMsg.sendToTarget();
               } catch (IOException e) {
                   Log.d(TAG, "Input stream was disconnected", e);
                   break;
               }
           }
       }

       // Call this from the main activity to send data to the remote device.
       public void write(byte[] bytes) {
           try {
               mmOutStream.write(bytes);

               // Share the sent message with the UI activity.
               Message writtenMsg = handler.obtainMessage(
                       MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
               writtenMsg.sendToTarget();
           } catch (IOException e) {
               Log.e(TAG, "Error occurred when sending data", e);

               // Send a failure message back to the activity.
               Message writeErrorMsg =
                       handler.obtainMessage(MessageConstants.MESSAGE_TOAST);
               Bundle bundle = new Bundle();
               bundle.putString("toast",
                       "Couldn't send data to the other device");
               writeErrorMsg.setData(bundle);
               handler.sendMessage(writeErrorMsg);
           }
       }

       // Call this method from the main activity to shut down the connection.
       public void cancel() {
           try {
               mmSocket.close();
           } catch (IOException e) {
               Log.e(TAG, "Could not close the connect socket", e);
           }
       }
   }
}

Une fois que le constructeur a acquis les flux nécessaires, le thread attend les données à passer par InputStream. Lorsque read(byte[]) renvoie des données de les données sont envoyées à l'activité principale à l'aide d'un membre Handler de la classe parente. Le fil de discussion attend ensuite que d'autres octets soient lus à partir de InputStream.

Pour envoyer des données sortantes, appelez la méthode write() du thread à partir de l'objet main et les octets à envoyer. Cette méthode appelle write(byte[]) pour envoyer les données à l'appareil distant. Si un IOException est généré lors de l'appel write(byte[]), le thread envoie un toast à l'activité principale, en expliquant à à l'utilisateur que l'appareil n'a pas pu envoyer les octets donnés à l'autre (connecté).

La méthode cancel() du thread vous permet d'arrêter la connexion à tout moment en fermant BluetoothSocket. Toujours appeler cette méthode lorsque vous avez terminé à l'aide de la connexion Bluetooth.

Pour une démonstration de l'utilisation des API Bluetooth, voir l'exemple de chat Bluetooth l'appli sur GitHub.