2012-02-14 59 views
4

我使用android示例代碼進行修改。只希望接收包 但是,我的代碼只修改這裏藍牙SPP收到一些包的幀可能丟失或?

private final Handler mHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
     case MESSAGE_STATE_CHANGE: 
      if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); 
      switch (msg.arg1) { 
      case BluetoothChatService.STATE_CONNECTED: 
       mTitle.setText(R.string.title_connected_to); 
       mTitle.append(mConnectedDeviceName); 
       mConversationArrayAdapter.clear(); 
       break; 
      case BluetoothChatService.STATE_CONNECTING: 
       mTitle.setText(R.string.title_connecting); 
       break; 
      case BluetoothChatService.STATE_LISTEN: 
      case BluetoothChatService.STATE_NONE: 
       mTitle.setText(R.string.title_not_connected); 
       break; 
      } 
      break; 
     case MESSAGE_WRITE: 
      byte[] writeBuf = (byte[]) msg.obj; 
      // construct a string from the buffer 
      String writeMessage = new String(writeBuf); 
      mConversationArrayAdapter.add(writeMessage); 
      break; 
     case MESSAGE_READ: 

      byte[] readBuf = (byte[]) msg.obj; 
      // construct a string from the valid bytes in the buffer 
      //String readMessage = new String(readBuf, 0, msg.arg1); 
      //String readMessage = BytesTrans_fill.bytesToHexString(readBuf); 
      Log.d("read", BytesTrans.bytes2HexString(readBuf,msg.arg1)); 
      String readMessage = BytesTrans.bytes2HexString(readBuf,msg.arg1); 
      ppV.setText(ppV.getText().toString() + readMessage + "★"); 
      break; 
     case MESSAGE_DEVICE_NAME: 
      // save the connected device's name 
      mConnectedDeviceName = msg.getData().getString(
        DEVICE_NAME); 
      Toast.makeText(getApplicationContext(), "Connected to " 
          + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); 
      break; 
     case MESSAGE_TOAST: 
      Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), 
          Toast.LENGTH_SHORT).show(); 
      break; 
     } 
    } 
}; 

和BluetoothChatService

public void run() { 
     Log.i(TAG, "BEGIN mConnectedThread"); 

     byte[] buffer = new byte[1024]; 

     int bytes; 

     // Keep listening to the InputStream while connected 
     while (true) { 
      try { 
       // Read from the InputStream 
       bytes = mmInStream.read(buffer); 

       // Send the obtained bytes to the UI Activity 
       mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer) 
         .sendToTarget(); 
      } catch (IOException e) { 
       Log.e(TAG, "disconnected", e); 
       connectionLost(); 
       break; 
      } 
     } 
    } 

,並添加此功能

package com.example.android.BluetoothChat; 

public class BytesTrans { 
    public static String byte2HexString(byte b) { 
     String ret = ""; 
      String hex = Integer.toHexString(b & 0xFF); 
      if (hex.length() == 1) { 
       hex = '0' + hex; 
      } 
      ret += hex.toUpperCase() + " "; 
     return ret; 
    } 

    public static String bytes2HexString(byte[] b, int count) { 
     String ret = ""; 
     for (int i = 0; i < count; i++) { 
      String hex = Integer.toHexString(b[i] & 0xFF); 
      if (hex.length() == 1) { 
       hex = '0' + hex; 
      } 
      ret += hex.toUpperCase() + " "; 
     } 
     return ret; 
    } 
    /*public static String String2byte(String b) 
    { 
     String[] ttt; 
     for (int i = 0; i < b.length(); i++) 
     { 
      for (int j= i; j<=i+1; j++) 
      { 
       ttt[i] = b; 
      } 

     }   

     String ttmp = ""; 
     String tmp = ""; 





     ret += tmp; 
    }*/ 
    public static int hexToTen(String b) { 
     int D2 = Integer.parseInt(b,16); 


     return D2; 
     } 
    } 

但此方案顯示有時甚至不是我的發送包的框架

我發送類似th是:

aa07210820001202140934390000000000000000000000000000000000000000000297c0fe6b

但有時收到包:

aa000297c0fe6b02131452470000000000000000000000000000000000000000000297c0fe6b

我怎樣才能改變我的代碼,即可獲得完整的軟件包的框架

+0

感謝您的回答,非常詳細。因爲這隻使用bluetoothChat例子,所以我只貼修改地方。我不明白,爲什麼這個代碼會產生這個問題。直到現在我還沒有搜索這個bug。你能給我一些教導嗎?非常感謝。 – user1206629 2012-02-15 01:09:44

回答

2

您還沒有表現出任何的藍牙接口代碼。但是,如果這主要基於BluetoothChat示例,那麼BluetoothChat示例存在一個簡單的問題:基本上,當從Bluetooth套接字製作read()並將其放入字節數組中時,該數組引用會跨越就像你在做的那樣使用Handler。實際的問題是,如果使用BluetoothChat示例以比打字速度更快的速度接收數據,則會看到字符丟失或變得混亂,因爲後續的read()正在覆蓋陣列,而UI仍在讀取數組來提取接收到的最後一串字符。

所以,如果你的MESSAGE_WRITE對象包含一個你調用套接字read()的數組引用,那麼這可能就是你丟失字符的原因。因此,請嘗試使用Arrays.copyOf()Message中發送陣列的副本。或者,也許有一個可以使用的循環緩衝區安排。

當我使用BluetoothChat示例作爲我的項目基礎時,我確實遇到了這個問題。我個人爲解決這個問題做了些什麼(並且不需要複製緩衝區等)是通過一個機制來實現一個機制,通過這個機制,我可以通過一個機制來告訴藍牙連接線程(包含阻塞套接字.read()的線程)方法調用,我期望響應有多少字節(幸運的是,我正在處理的協議允許瞭解響應長度)。然後,連接線程僅在收到完整響應時發送Message,而不是將響應的片段發送到UI的幾個Message

0

這是我的解決方案,使用Android聊天示例代碼。這只是一個可能的解決方案。我收到的消息以\n結束。我正在使用此線程讀取來自通過藍牙連接的Arduino的消息。在Arduino上,我可以確保每條消息都以\n結尾,使用Serial.println(buffer);

我收到的所有內容都附加到現有字符串(queue變量)。當我在這個大字符串上有一整行時,我將它發送到活動並從queue變量中刪除它。

public void run() { 
     Log.i(TAG, "BEGIN mConnectedThread"); 
     byte[] buffer = new byte[1024]; 
     int bytes, pos; 
     StringBuilder queue = new StringBuilder(""); 
     String temp; 
     // Keep listening to the InputStream while connected 
     while (true) { 
      try { 
       bytes = mmInStream.read(buffer); 
       if (bytes > 0) { 
        String readMessage = new String(buffer, 0, bytes); 
        queue.append(readMessage); 
        pos = queue.indexOf("\n"); 
        while (pos >= 0) { 
         // Log.d("Temperatura", "indexOf() #" + pos); 
         temp = queue.substring(0, pos - 1); 
         queue.delete(0, pos + 1); 
         mHandler.obtainMessage(Constants.MESSAGE_READ, 0, 0, temp).sendToTarget(); 
         pos = queue.indexOf("\n"); 
        } 
       } 
      } catch (IOException e) { 
       Log.e(TAG, "disconnected", e); 
       connectionLost(); 
       // Start the service over to restart listening mode 
       BluetoothChatService.this.start(); 
       break; 
      } 
     } 
    }