作者簡介? 創(chuàng)微信公眾號(hào)郭霖 WeChat ID: guolin_blog
早上好,五一放假回來的第二天,相信大家已經(jīng)回到工作狀態(tài)了吧,那么我們今天繼續(xù)分享干貨。
本篇來自Xanthuim的投稿,介紹了藍(lán)牙常見的使用方式,并分享了自己的項(xiàng)目,希望對(duì)大家有所幫助。
Xanthuim的博客地址:
http://blog.csdn.net/qq_15003505
前言
最近在工作中使用到藍(lán)牙的功能,當(dāng)然我們這個(gè)藍(lán)牙時(shí)跟藍(lán)牙芯片結(jié)合使用的,而不是手機(jī)跟手機(jī)連接通信的。其實(shí)本質(zhì)時(shí)差不多的,只是設(shè)備不一樣罷了。在這里我不會(huì)貼出藍(lán)牙那些協(xié)議等等復(fù)雜的名詞解釋,因?yàn)檫@個(gè)不是一兩句話能解釋的清楚,在我們先不太了解藍(lán)牙的這些專業(yè)名詞之前,我們先掌握它的基本使用就可以了,后續(xù)如果想深入了解的話,我們?cè)倩〞r(shí)間去學(xué)習(xí)。本文介紹的低功耗的藍(lán)牙,是?Android?4.3 才開始支持的,而要使用傳統(tǒng)藍(lán)牙和高版本的藍(lán)牙請(qǐng)參照官方文檔,有中文介紹哦。
官方藍(lán)牙文檔
https://developer.android.google.cn/guide/topics/connectivity/bluetooth.html
官方不同版本藍(lán)牙示例(有3個(gè)):
https://github.com/googlesamples?utf8=%E2%9C%93&q=bluetooth&type=&language=
藍(lán)牙基本使用流程
從圖上可以看出我這個(gè)例子只是單方面的通信,即手機(jī)只接收數(shù)據(jù)而不發(fā)送數(shù)據(jù)。
藍(lán)牙關(guān)鍵類
BluetoothManager:藍(lán)牙管理服務(wù),如果對(duì)Android基本框架熟悉的話,你會(huì)發(fā)現(xiàn)藍(lán)牙也屬于最底層的驅(qū)動(dòng)模塊里,那么要使用藍(lán)牙的東西就需要使用 (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE) 來獲取了。不過看是把圖貼一下。
BluetoothAdapter:表示本地設(shè)備藍(lán)牙適配器。 BluetoothAdapter 允許您執(zhí)行基本的藍(lán)牙任務(wù),例如啟動(dòng)設(shè)備發(fā)現(xiàn),查詢已綁定(配對(duì))設(shè)備的列表,使用已知MAC地址實(shí)例化 BluetoothDevice,并創(chuàng)建一個(gè) BluetoothServerSocket 以監(jiān)聽來自其他設(shè)備的連接請(qǐng)求,并啟動(dòng)掃描藍(lán)牙LE設(shè)備。這個(gè)類時(shí)關(guān)鍵類,后面會(huì)大量使用到它。
BluetoothAdapter.LeScanCallback:用于提供LE掃描結(jié)果的回調(diào)界面。這個(gè)類就是掃描的回調(diào)接口,不過在?Android 5.0以上 使用抽象類 ScanCallback。
BluetoothLeScanner:該類提供了對(duì)藍(lán)牙LE設(shè)備執(zhí)行掃描相關(guān)操作的方法。應(yīng)用程序可以使用 ScanFilter 掃描特定類型的藍(lán)牙LE設(shè)備。它還可以請(qǐng)求不同類型的回調(diào)來傳遞結(jié)果。不過這個(gè)類是在 Android 5.0(API21)以上才出現(xiàn)的,也就是對(duì)于Android 4.3的以上我們只會(huì)使用 BluetoothAdapter 來進(jìn)行掃描等操作,當(dāng)然如果是5.0以上的可以使用這個(gè)類來代替的。
ScanCallback:藍(lán)牙LE掃描回調(diào),使用這些回調(diào)報(bào)告掃描結(jié)果。這個(gè)是抽象類與 BluetoothLeScanner 配套使用。
BluetoothDevice:表示遠(yuǎn)程藍(lán)牙設(shè)備,BluetoothDevice 允許您創(chuàng)建與相應(yīng)設(shè)備的連接或關(guān)于它的查詢信息,例如名稱,地址,類和綁定狀態(tài)。
BluetoothProfile:配置文件代理。每個(gè)公共配置文件實(shí)現(xiàn)這個(gè)接口。它有幾個(gè)直接子類,每個(gè)子類再不同場景中使用,如 BluetoothA2dp, BluetoothGatt, BluetoothGattServer, BluetoothHeadset, BluetoothHealth。在當(dāng)前例子中使用到的是 BluetoothGatt。
BluetoothGatt:該類提供藍(lán)牙GATT功能,以實(shí)現(xiàn)與藍(lán)牙智能或智能就緒設(shè)備的通信。后續(xù)使用該類做連接、斷開、關(guān)閉等操作。
BluetoothGattCallback:文檔沒有直接的解釋,只說了被用在連接設(shè)備時(shí)候的回調(diào)。雖然文檔沒有詳細(xì)說明,但是這個(gè)回調(diào)會(huì)在后續(xù)的連接、斷開、通信中起到關(guān)鍵作用。
好了,主要的幾個(gè)類介紹的差不多了。接下來我們使用這幾個(gè)類練習(xí)一下。
1、獲取藍(lán)牙管理服務(wù)和適配器
獲取了適配器后,我們可以通過適配器是否為null來判斷是否支持藍(lán)牙功能(想必現(xiàn)在的手機(jī)應(yīng)該都支持吧)。另外適配器還提供了以下的方法:
上面的就是啟用、關(guān)閉、掃描、停止的幾個(gè)方法。需要注意的是在啟用藍(lán)牙的時(shí)候在不同手機(jī)會(huì)彈出啟用對(duì)話框,比如魅族。那么這個(gè)時(shí)候你需要通過 isEnabled方法 來判斷是否啟用了,如果沒有啟用則使用 startActivity 來啟用,然后通過 Activity 或者 Fragment 的 onActivityResult 回調(diào)方法來做余下的操作了。
startActivityForResult(newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE),REQUEST_ENABLE);
好了,使用上面的掃描方法就可以掃描到藍(lán)牙設(shè)備了,是不是很簡單啊。再說明一下,上面的 leScanCallback 就是上面提到的?BluetoothAdapter.LeScanCallback,你需要實(shí)現(xiàn)它就可以了。
2、權(quán)限配置
不過使用藍(lán)牙也是要配置權(quán)限的,如果你沒有在 Manifest 中配置,在 Android Studio 中使用上面的方法的時(shí)候它會(huì)報(bào)錯(cuò)要求你加入權(quán)限。我在這里列一下我使用到的權(quán)限:
是的,你會(huì)發(fā)現(xiàn)使用藍(lán)牙還需要位置權(quán)限?我開始也覺得一個(gè)藍(lán)牙也要位置權(quán)限,后來在翻看官方文檔的時(shí)候才知道的,不然你在5.0以上的手機(jī)上掃不出藍(lán)牙的!詳情請(qǐng)翻閱官方文檔:
https://developer.android.google.cn/guide/topics/connectivity/bluetooth-le.html#user-permission
3、連接設(shè)備
有了藍(lán)牙設(shè)備后接下來我們連接下,然后發(fā)發(fā)數(shù)據(jù)看看。連接設(shè)備其實(shí)也很簡單,就是通過掃描到的藍(lán)牙設(shè)備對(duì)象來連接即可。藍(lán)牙設(shè)備就是上面提到的 BluetoothDevice,這個(gè)類有一個(gè)方法:
第一個(gè) Context 就不說了;第二個(gè)參數(shù) autoConnect 的解釋是“是否直接連接到遠(yuǎn)程設(shè)備(false)或一旦遠(yuǎn)程設(shè)備可用即可自動(dòng)連接(true)”;第三個(gè)參數(shù)也是上面提到的抽象類,這個(gè)類在連接過程中起到關(guān)鍵作用。最后方法會(huì)返回一個(gè) BluetoothGatt 對(duì)象,后續(xù)我們通過這個(gè)對(duì)象可以重連、斷開、關(guān)閉設(shè)備。貼下我例子中的連接方法:
抽象類:
這個(gè)類里面有很多方法,不過都被這個(gè)類實(shí)現(xiàn)了,我們根據(jù)自己的情況來重寫。解釋下上面列出的方法:
onConnectionStateChange:監(jiān)測藍(lán)牙設(shè)備的連接、斷開、讀取設(shè)備信號(hào)強(qiáng)度值、發(fā)現(xiàn)服務(wù)(翻譯的好別扭)。連接和斷開可以通過 newState參數(shù) 來判斷,注意是和 BluetoothProfile 的常量值來對(duì)比的,這個(gè)類也是上面提到過的。其實(shí)這個(gè)類提供了4個(gè)狀態(tài)值,只不過在使用過程中只有 連接(狀態(tài)值2)和 斷開(狀態(tài)值0),其他的沒用到。
至于后面的讀取設(shè)備信號(hào)強(qiáng)度值、發(fā)現(xiàn)服務(wù)這兩個(gè)分別用在獲取信號(hào)強(qiáng)度和通信的。怎么解釋?要知道藍(lán)牙也是無線傳輸?shù)模热皇菬o線就跟移動(dòng)網(wǎng)、WIFI一樣都存在信號(hào)強(qiáng)弱的情況,那么通過這個(gè)就可以獲取了。信號(hào)強(qiáng)度值是負(fù)數(shù),負(fù)數(shù)越大信號(hào)越好(最大理論值是0),單位是dBm。而發(fā)現(xiàn)服務(wù),我們?cè)诔晒B接后調(diào)用 gatt.discoverServices() 方法既可以獲取與連接的設(shè)備進(jìn)行通信了,最后回調(diào) onServicesDiscovered 方法。
onServicesDiscovered:這個(gè)方法里面我們需要做的就是使用藍(lán)牙的 UUID 獲取服務(wù)、特征、描述等對(duì)象,然后就可以給手機(jī)發(fā)送數(shù)據(jù)了。這里需要注意的是 UUID 不能隨便寫,而是設(shè)備廠商或者通用的 UUID,否則你是無法使用的。說到這個(gè) UUID,其實(shí)我也比較迷惑的,很多文章在介紹 UUID 的時(shí)候都是一筆帶過或者直接拿來用根本不解釋這是干嘛的,而且也沒找到一個(gè)比較全面介紹藍(lán)牙協(xié)議等專業(yè)文檔(誰找到了,麻煩給我留一個(gè)地址)。其實(shí)說到這,里面提到的特征、描述等對(duì)象,我也沒詳細(xì)去說請(qǐng)?jiān)彙?/p>
onCharacteristicChanged:遠(yuǎn)程特性通知,回調(diào)觸發(fā)。就是上面執(zhí)行完后,只要連接的設(shè)備觸發(fā)某些動(dòng)作(比如我的藍(lán)牙芯片按鈕按下、抬起),這個(gè)方法就會(huì)被調(diào)用了。然后我們?cè)谶@個(gè)方法中就可以獲取遠(yuǎn)程設(shè)備發(fā)過來的信息。
好了,其實(shí)寫到我這個(gè)例子基本的使用已經(jīng)差不多了,剩下的無法就是藍(lán)牙的斷開、連接、關(guān)閉(釋放資源)
最后,貼下我的例子截圖以及我使用的藍(lán)牙芯片,是不是感覺高大上啊,哈哈~
好了,我這個(gè)藍(lán)牙芯片在連接之前的LED指示燈是一閃一閃的,而連接成功后就會(huì)常亮的。上圖的3個(gè)按鈕也是對(duì)應(yīng)芯片的按鍵的。不夠在這里說明一下,由于為了保密,我這里不會(huì)放出與藍(lán)牙芯片的例子,而是單獨(dú)寫了一個(gè)簡單的例子,不過底層的東西是不變的。另外這個(gè)是單方面的通信交互,如何做到雙向通信呢?由于本例子只需要單向通信,所以就沒涉及到,不夠也是上面的例子的范疇,大家可以自己去研究下。另外說明下官方提供的低功耗的例子在使用“發(fā)現(xiàn)服務(wù)”的那個(gè)回調(diào)方法存在問題(連接了接收不到數(shù)據(jù)),我這里跟官方的例子還是不一樣的。
另外說明下,我的 Android Studio 版本是2.4 preview 3版本,對(duì)應(yīng)的 gradle 版本是 gradle-3.4.1-all,所有低版本的自行修改配置。
GitHub地址:
https://github.com/Xanthuim/BluetoothSample
文章原創(chuàng)作者GuoLin 書籍推薦
郭林大神原創(chuàng)android 書籍:《第一行代碼 android》