انتقال داده‌های بلوتوث

پس‌از اینکه باموفقیت به دستگاه بلوتوث متصل شدید، هرکدام از آن‌ها BluetoothSocket متصل‌شده‌ای دارند. اکنون می‌توانید اطلاعات را بین دستگاه‌ها هم‌رسانی کنید. بااستفاده از BluetoothSocket، روال کلی برای انتقال داده‌ها به‌صورت زیر است:

  1. InputStream و OutputStream را که انتقال‌ها را ازطریق سوکت بااستفاده از getInputStream() و getOutputStream() به‌ترتیب مدیریت می‌کنند دریافت کنید.

  2. خواندن و نوشتن داده‌ها در جاری‌سازی‌ها بااستفاده از read(byte[]) و write(byte[]).

البته جزئیات پیاده‌سازی وجود دارد که باید درنظر گرفته شود. به‌طور خاص، باید از رشته اختصاصی برای خواندن از جاری‌سازی و نوشتن در آن استفاده کنید. این موضوع مهم است زیرا هر دو روش read(byte[]) و write(byte[]) تماس‌ها را مسدود می‌کنند. روش read(byte[]) تا زمانی که چیزی برای خواندن از جاری‌سازی وجود داشته باشد مسدود می‌شود. روش write(byte[]) معمولاً مسدود نمی‌کند، اما می‌تواند برای کنترل جریان مسدود کند اگر دستگاه ازراه‌دور read(byte[]) را به‌اندازه کافی سریع فراخوانی نکند و درنتیجه میانگیرهای واسطه پر شوند. بنابراین، باید حلقه اصلی خود را در رشته به خواندن از InputStream اختصاص دهید. می‌توانید از روش عمومی جداگانه‌ای در رشته برای شروع نوشتن در OutputStream استفاده کنید.

مثال

در زیر مثالی از نحوه انتقال داده بین دو دستگاه متصل‌شده ازطریق بلوتوث آورده شده است:

کاتلین

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
           // or read() returns -1
           while (true) {
               // Read from the InputStream.
               try {
                   numBytes = mmInStream.read(mmBuffer)
                   if (numBytes < 0) {
                       Log.i(TAG, "returns -1, Input stream disconnected")
                       break
                   }
               } 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)
           }
       }
   }
}

جاوا

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);
                   if (numBytes < 0) {
                        Log.i(TAG, "Read return -1, Input stream disconnected");
                        break;
                   }
                   // 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);
           }
       }
   }
}

پس‌از اینکه سازنده جریان‌های لازم را به‌دست آورد، رشته منتظر می‌ماند تا داده‌ها ازطریق InputStream وارد شوند. وقتی read(byte[]) با داده‌های جاری برمی‌گردد، داده‌ها بااستفاده از عضو Handler از کلاس والد به فعالیت اصلی ارسال می‌شود. سپس رشته منتظر می‌ماند تا بایت‌های بیشتری از InputStream خوانده شود.

برای ارسال داده‌های خروجی، روش write() رشته را از فعالیت اصلی فراخوانی می‌کنید و بایت‌های ارسالی را ارسال می‌کنید. این روش write(byte[]) را فراخوانی می‌کند تا داده‌ها را به دستگاه ازراه‌دور ارسال کند. اگر IOException هنگام فراخوانی write(byte[]) ایجاد شود، رشته یک پیام زودگذر به فعالیت اصلی ارسال می‌کند و به کاربر توضیح می‌دهد که دستگاه نتوانسته است بایت‌های داده‌شده را به دستگاه دیگر (متصل) ارسال کند.

روش cancel() رشته به شما امکان می‌دهد اتصال را هرزمان خواستید با بستن BluetoothSocket قطع کنید. همیشه وقتی کارتان با اتصال بلوتوث تمام شد، این روش را فراخوانی کنید.

برای نمایش نحوه استفاده از Bluetooth API، برنامه نمونه Bluetooth Chat را در GitHub ببینید.