android 藍牙編程重點---如何發送和接收16進制數據


     最近的android藍牙開發項目也逐漸接近尾聲,基本的功能都已經完成,只剩下界面的設計。現在真的是舒了一口氣!

     作為編程學習經驗只有1年的菜鳥,這是我獨自完成的商業性產品,而且還是涉及到與單片機藍牙模塊的底層通信,難度自然不小。最大的難度不是知識點不懂,而是調試,因為干擾因素實在是太多,很難找出是軟件的問題還是硬件的問題,所以,在代碼中一定要設置好調試點,以方便查詢問題的症結點。

      線程也是一個考慮的因素。凡是涉及到I/O的編程,都是一個不小的難題,因為它里面會涉及到線程問題。java的線程庫的確非常方便好用,但要想正確的使用還是一個值得研究的話題,最壞的情況就是我們胡亂的使用線程技巧結果導致無謂的線程開銷。

      當然,這里的線程還是非常簡單,關於同步,鎖機制這些高級的話題根本沒有用到,基本的線程知識就已經夠用了。

      與藍牙模塊通信最重要的地方就是數據的發送和接收,因為是底層的操作,所以更多是發送16進制數據。

      進制轉換是我們程序員的必修課,屬於基本素質。這里需要的是將字節數組轉化為16進制字符串,方法都是通用的:

 public static String bytesToHexString(byte[] bytes) {
        String result = "";
        for (int i = 0; i < bytes.length; i++) {
            String hexString = Integer.toHexString(bytes[i] & 0xFF);
            if (hexString.length() == 1) {
                hexString = '0' + hexString;
            }
            result += hexString.toUpperCase();
        }
        return result;
    }

     接下來就是發送數據。

     發送數據非常簡單,之前有關於藍牙編程的博文已經講到了,http://www.cnblogs.com/wenjiang/p/3200138.html,這里只講重要的一點:大容量字節數組的發送。

     我們需要發送64個字節的數組,如果一次性發送過去,單片機那里可能無法及時處理以致沒有任何回應,因為單片機那里是設置了數據接收的延時時間。要想暢通的與藍牙模塊通信,考慮這個時間差非常重要。調整字節的發送速率,就成為非常關鍵的一步。值得注意的是,數據的發送是非常快的,就是因為這樣才會導致單片機那里無法及時處理,所以,每次發送后的延時是非常重要的。我們單片機那里的延時是10毫秒,所以我們選擇發送完每個字節后就延時10毫秒再發下個字節。

 for (byte b : bytes) {
     out.write(b);
     Thread.sleep(10);
 }

     具體的延時時間和字節發送速率得看單片機那里程序的設置。
     在使用InputStream的時候,必須注意,InputStream的讀取是阻塞的。這點在一般的情況下是不會影響到我們的程序,但是記住這個情況對於代碼的設計是非常重要的,尤其是在考慮用戶體驗的時候。

     無參數的read()是每次只從流中讀取一個字節,這種做法效率非常低,但是簡單,像是讀取整數值這種情況,使用read()就非常好,但如果是16進制字符串呢?使用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,這樣一次就能讀取多個字節。

      如果是讀取多個字節,我們常常使用InputStream.available()方法來獲取數據流中可讀字節的個數。讀取本地數據的時候,該方法發揮得非常好,但如果是讀取非本地數據,就可能出現字節遺漏的問題,像是要讀取100個字節,可能就是90個,甚至是0個。

      出現0個的情況就是單片機那邊沒有響應或者字節還沒發送過來,這時我們就需要一個循環來保證我們能夠拿到數據:

  int count = 0;
  while (count == 0) {
   count = in.available();
  }
  byte[] bytes = new byte[count];
  in.read(bytes);

      但像是上面的90個字節的情況就是字節遺漏。對於這種情況,解決方法也很簡單:

  byte[] bytes = new byte[count];
  int readCount = 0; // 已經成功讀取的字節的個數
  while (readCount < count) {
   readCount += in.read(bytes, readCount, count - readCount);
  }

      最好是這么寫,因為Java的API已經明確的告訴我們,read()方法並不能保證讀取到我們想要的字節數。
      這樣我們就能解決16進制數據的發送和讀取了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM