نقل بيانات البلوتوث

بعد الاتصال بجهاز يتضمّن بلوتوث بنجاح، يكون لكل جهاز BluetoothSocket متصل. يمكنك الآن مشاركة المعلومات بين الأجهزة. باستخدام BluetoothSocket، يكون الإجراء العام لنقل البيانات على النحو التالي:

  1. يمكنك الحصول على InputStream وOutputStream اللتين تعالجان عمليات الإرسال عبر المقبس باستخدام getInputStream() و getOutputStream() على التوالي.

  2. قراءة البيانات وكتابتها في ساحات المشاركات باستخدام read(byte[]) و write(byte[]).

وبطبيعة الحال، توجد تفاصيل التنفيذ التي يجب أخذها في الاعتبار. وعلى وجه الخصوص، يجب عليك استخدام سلسلة سلاسل مخصصة للقراءة من البث والكتابة إليه. وهذا الإجراء مهم لأنّ الطريقتين read(byte[]) وwrite(byte[]) تحظران المكالمات. يتم حظر استخدام طريقة read(byte[]) إلى أن يتوفر محتوى يمكن قراءته من ساحة المشاركات. لا تحظر طريقة write(byte[]) عادةً، ولكن يمكن أن تحظر إمكانية التحكم في التدفق إذا كان الجهاز البعيد لا يتصل بـ read(byte[]) بسرعة كافية وتمتلئ الموارد الاحتياطية المتوسطة نتيجة لذلك. لذلك، يجب تخصيص الحلقة الرئيسية في سلسلة التعليمات للقراءة من InputStream. يمكنك استخدام طريقة علنية منفصلة في سلسلة المحادثات لبدء عمليات الكتابة على OutputStream.

مثال

في ما يلي مثال على كيفية نقل البيانات بين جهازين متصلين عبر البلوتوث:

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);
           }
       }
   }
}

بعد أن تكتسب الدالة الإنشائية ساحات المشاركات اللازمة، تنتظر سلسلة التعليمات حتى تصل البيانات من خلال InputStream. عند عودة read(byte[]) مع بيانات من ساحة المشاركات، يتم إرسال البيانات إلى النشاط الرئيسي من خلال عضو Handler من الصف الرئيسي. تنتظر سلسلة التعليمات بعد ذلك أن تتم قراءة المزيد من وحدات البايت من InputStream.

لإرسال البيانات الصادرة، عليك استدعاء طريقة write() الخاصة بسلسلة المحادثات من النشاط الرئيسي وتمرير وحدات البايت المُراد إرسالها. تستدعي هذه الطريقة write(byte[]) لإرسال البيانات إلى الجهاز البعيد. وإذا تم عرض IOException عند الاتصال بـ write(byte[])، ترسل سلسلة المحادثات إشعارًا نخبًا إلى النشاط الرئيسي لتشرح للمستخدم أنّ الجهاز لا يمكنه إرسال وحدات البايت المحدّدة إلى الجهاز الآخر (المتصل).

تتيح لك طريقة cancel() الخاصة بسلسلة المحادثات إنهاء الاتصال في أي وقت عن طريق إغلاق BluetoothSocket. قم دائمًا باستدعاء هذه الطريقة عند الانتهاء من استخدام اتصال البلوتوث.

لعرض توضيحي لاستخدام واجهات برمجة التطبيقات Bluetooth، يُرجى الاطّلاع على نموذج تطبيق Bluetooth Chat على GitHub.