藍牙開發(fā)的細節(jié)(數據傳輸)

藍牙數據傳輸問題

對于藍牙來說google已經封裝好了很多api所以使用起來并不會很難,但是實際開發(fā)中藍牙開發(fā)最頭疼的問題不是如何去調用api,而是數據的交互方面,如長連接,數據續(xù)傳,硬件接受速率等問題.

打開藍牙有幾種方式?

首先我們先了解下幾種常用的打開方式.

  • 第一種方法相對簡單,直接調用系統(tǒng)對話框啟動藍牙:
    在AndroidManifest文件中添加需要的權限,高版本也不需要動態(tài)授權:
<uses-permission android:name="android.permission.BLUETOOTH" />
//處理回調對話框
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);
  • 第二種方法,靜默開啟,不會有方法一的對話框:
    在AndroidManifest文件中添加需要的權限:
  • 在AndroidManifest中配置需要的權限.
  • 對于6.0的運行時權限進行適配,在java中動態(tài)授權.
  • 最后直接調api開啟
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.enable(); //開啟
//mBluetoothAdapter.disable(); //關閉

如何搜索藍牙設備?

搜索分為:主動搜索和被動搜索。

  • 主動搜索
  • 創(chuàng)建BluetoothAdapter對象
  • 配對的藍牙設備列表
  • 定義發(fā)送接收廣播

藍牙的UUID是什么?有什么用?

UUID(Universally Unique Identifier) 統(tǒng)一表示定義.
藍牙是通過串口發(fā)送AT命令,藍牙默認是在數據模式的,要配置為AT命令模式,對其進行設置,不過UUID在出廠前是設置過的.
對于藍牙設備,每個服務都有一個與它對應的UUID(唯一的).
如:
信息同步服務:00001104-0000-1000-8000-00805F9B34FB 文件傳輸服務:00001106-0000-1000-8000-00805F9B34FB

如何使用藍牙進行數據傳輸?

藍牙模塊通信最重要的地方就是數據的發(fā)送和接收,其傳輸數據與Socket類似。

  • 在網絡中使用Socket和ServerSocket控制客戶端和服務端的數據讀寫。
  • 而藍牙通訊也由客戶端和服務端Socket來完成。藍牙客戶端Socket是BluetoothSocket,藍牙服務端Socket是BluetoothServerSocket。這兩個類都在android.bluetooth包中。
  • 無論是BluetoothSocket,還是BluetoothServerSocket,都需要一個UUID(全局唯一標識符,Universally Unique Identifier),UUID相當于Socket的端口,而藍牙地址相當于Socket的IP。

實際開發(fā)中需要注意的地方.

需要注意的

  1. 因為涉及涉及到I/O編程,所以需要注意兩端的編碼'utf-8'要一致.
  2. 客戶端與服務端的UUID也要相同.
  3. 藍牙屬于底層數據傳輸,所以實際開發(fā)更多發(fā)送的是16進制數據.
  4. 因為涉及到了I/O編程,所以對線程控制這塊(同步,鎖機制)需要注意使用.
  5. 對于一些大容量字節(jié)數組的發(fā)送需要注意的地方.
  6. 為了用戶更好的體檢避免流量的過度浪費,使用阻塞式的InputStream讀取.

1. 因為涉及涉及到I/O編程,所以需要注意兩端的編碼'utf-8'要一致.

os.write("datas....".getBytes("utf-8"));

2. 客戶端與服務端的UUID也要相同.

//客戶端Socket
device.createRfcommSocketToServiceRecord(MY_UUID);
//服務端Socket
mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);

3. 藍牙屬于底層數據傳輸,所以實際開發(fā)更多發(fā)送的是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;
    }

5. 對于一些大容量字節(jié)數組的發(fā)送需要注意的地方.

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

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

6.為了用戶更好的體檢避免流量的過度浪費,使用阻塞式的InputStream讀取.

在使用InputStream的時候,必須注意,InputStream的讀取是阻塞的。這點在一般的情況下是不會影響到我們的程序,但是記住這個情況對于代碼的設計是非常重要的,尤其是在考慮用戶體驗的時候。
無參數的read()是每次只從流中讀取一個字節(jié),這種做法效率非常低,但是簡單,像是讀取整數值這種情況,使用read()就非常好,但如果是16進制字符串呢?使用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,這樣一次就能讀取多個字節(jié)。
如果是讀取多個字節(jié),我們常常使用InputStream.available()方法來獲取數據流中可讀字節(jié)的個數。讀取本地數據的時候,該方法發(fā)揮得非常好,但如果是讀取非本地數據,就可能出現字節(jié)遺漏的問題,像是要讀取100個字節(jié),可能就是90個,甚至是0個。
出現0個的情況就是單片機那邊沒有響應或者字節(jié)還沒發(fā)送過來,這時我們就需要一個循環(huán)來保證我們能夠拿到數據:

  int count = 0;
  while (count == 0) {
   count = in.available();
  }
  byte[] bytes = new byte[count];
  in.read(bytes);
      但像是上面的90個字節(jié)的情況就是字節(jié)遺漏。對于這種情況,解決方法也很簡單:
  byte[] bytes = new byte[count];
  int readCount = 0; // 已經成功讀取的字節(jié)的個數
  while (readCount < count) {
   readCount += in.read(bytes, readCount, count - readCount);
  }

部分內容參考鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容

  • 藍牙 注:本文翻譯自https://developer.android.com/guide/topics/conn...
    RxCode閱讀 8,779評論 11 99
  • 國家電網公司企業(yè)標準(Q/GDW)- 面向對象的用電信息數據交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 11,075評論 6 13
  • 公司的項目最近需要用到藍牙開發(fā)的相關內容,因此特地查閱了Google官方文檔的內容并進行二次整理,希望能對需要學習...
    Chuckiefan閱讀 32,515評論 44 123
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 134,828評論 18 139
  • 在一個下著暴雨的黑夜里,一名穿著華麗的商人和一名饑寒交迫的和尚相繼跑進了一座寺廟里避雨。 那是座年...
    瑣碎布丁閱讀 580評論 1 1