Android BLE開發(fā)之初識(shí)GATT

前言

BLE是在Android 4.3上被引入的,并在android 5.0上加入了ble advertise的API支持。其時(shí),IOS上的BLE已經(jīng)玩的風(fēng)生水起,其中IOS的ANCS服務(wù)就是基于BLE封裝的通知下發(fā)協(xié)議,而IBeacon是基于BLE廣播的單向傳輸?shù)膽?yīng)用。
Android上的BLE開發(fā)算是個(gè)后發(fā)者,但是android開放了對(duì)BLE的支持后,我們就可以又很多好玩的東西可以嘗試了,比如以前IOS的藍(lán)牙是無法與Android的藍(lán)牙進(jìn)行通信的,有了BLE這就有了可能,還有讀取IOS的下發(fā)通知,自己實(shí)現(xiàn)和android手表的通信,讀取手環(huán)的數(shù)據(jù)等等有趣的東西。

而中文社區(qū)中關(guān)于Android BLE的開發(fā)資料幾乎全是android官網(wǎng)上BLE開發(fā)指南的原版翻譯,但是該網(wǎng)站上的內(nèi)容是基于Android 4.3來寫的,其中的API已經(jīng)過時(shí),最新的BLE API應(yīng)該是基于Android 5.0的,所以我根據(jù)官網(wǎng)的思路基于最新的API最簡單的方式介紹Android的BLE開發(fā)。
以后還會(huì)把跟BLE相關(guān)的內(nèi)容都整理下來,作為一個(gè)系列。

基本概念

想要進(jìn)行Ble相關(guān)的開發(fā),我們必須具備一定的基礎(chǔ)知識(shí),當(dāng)然基礎(chǔ)知識(shí)肯定是非常簡單的。

設(shè)備角色

首先要明白的是,這兩種角色的區(qū)分是硬件層面上,而且是成對(duì)出現(xiàn)的相對(duì)概念:
** 中心設(shè)備(Central device) **:功能相對(duì)強(qiáng)大,用來掃描和連接周邊設(shè)備的,例如手機(jī)、平板等
** 周邊設(shè)備(Central device) **:功能相對(duì)簡單,功耗較小,被中心設(shè)備連接以提供數(shù)據(jù)的,例如手環(huán)、智能體溫計(jì)等

其實(shí)從最根本上來講,它應(yīng)該是在對(duì)建立連接的過程不同角色的一種區(qū)分。我們知道藍(lán)牙設(shè)備要想讓別人知道自己的存在,是要不間斷的對(duì)外放松廣播的,而另外一方則需要掃描并回復(fù)該廣播包,這樣才能建立連接,在這個(gè)過程中,負(fù)責(zé)廣播的就是peripheral,而負(fù)責(zé)掃描的是Central。

關(guān)于兩者的連接過程需要注意:

  • 中心設(shè)備可以同時(shí)連接多個(gè)周邊設(shè)備。
  • 周邊設(shè)備一旦被連接上,立刻停止廣播,斷開后繼續(xù)廣播
  • 任何時(shí)候只能一個(gè)設(shè)備嘗試連接,排隊(duì)連接。
GATT

BLE技術(shù)是基于GATT進(jìn)行通信的,GATT是一種屬性傳輸協(xié)議,簡單的講可以認(rèn)為是一種屬性傳輸?shù)膽?yīng)用層協(xié)議。
它的結(jié)構(gòu)非常簡單:


GATT結(jié)構(gòu)圖

你可以把他看成xml來理解:

  • 每個(gè)GATT由完成不同功能的Service組成;
  • 每個(gè)Service由不同的Characteristic組成;
  • 每個(gè)Characteristic由一個(gè)value和一個(gè)或者多個(gè)Descriptor組成;
  • Service、Characteristic相當(dāng)于標(biāo)簽(Service相當(dāng)于他的類別,Characteristic相當(dāng)于它的名字),而value才真正的包含數(shù)據(jù),Descriptor是對(duì)這個(gè)value進(jìn)行的說明和描述,當(dāng)然我們可以從不同角度來描述和說明,因此可以有多個(gè)Descriptor.

這樣子理解可能不夠準(zhǔn)確,下面我們來舉一個(gè)簡單的例子進(jìn)行說明:

常見的小米手環(huán)是一個(gè)BLE設(shè)備,(假設(shè))它包含三個(gè)Service,分別是提供設(shè)備信息的Service、提供步數(shù)的Service、檢測心率的Service;
而設(shè)備信息的service中包含的characteristic包括廠商信息、硬件信息、版本信息等;而心率Service則包括心率characteristic等,而心率characteristic中的value則真正的包含心率的數(shù)據(jù),而descriptor則是對(duì)該value的描述說明,比如value的單位啊,描述啊,權(quán)限啊等。

GATT C/S

對(duì)GATT有了初步的了解,我們知道GATT是一種典型的C/S模式,既然是C/S那么我們就有必要對(duì)Server和client進(jìn)行區(qū)分。

** GATT server ** vs. ** GATT client **。這兩種角色存在的階段則是建立連接之后,根據(jù)對(duì)話地位的不同進(jìn)行區(qū)分的,很容易理解的是,保有數(shù)據(jù)的那一方我們稱之為GATT server,訪問數(shù)據(jù)的那一方我們稱之為GATT client。

這和我們之前提到的設(shè)備角色是不同層面的概念,有必要加以區(qū)分,我們還是用一個(gè)簡單的例子進(jìn)行說明:

以手機(jī)和手表的例子來進(jìn)行說明,手機(jī)和手機(jī)建立連接之前,我們都是用手機(jī)的藍(lán)牙搜索功能去搜索手表的藍(lán)牙設(shè)備,這個(gè)過程中很明顯手表在進(jìn)行BLE廣播以便其他設(shè)備知道自己的存在,它在這個(gè)過程中就是peripheral的角色,而手機(jī)負(fù)責(zé)掃描的任務(wù),自然扮演的就是Center了;兩者建立了GATT連接后,當(dāng)手機(jī)需要從手表中讀取步數(shù)等傳感器數(shù)據(jù)時(shí),兩者交互的數(shù)據(jù)是保存在手表中的,因此此時(shí)手表就是GATT server的角色,自然手機(jī)就作為GATT client;而當(dāng)手表想要從手機(jī)讀取短信電話等信息室,數(shù)據(jù)的保佑者又變成了手機(jī),所以此時(shí)手機(jī)就是server ,而手表則是client。

Service/Characteristic

上面我們已經(jīng)對(duì)他們有了感性的理解,接下來我們來一些實(shí)用的信息:

  1. Characteristic是最小的數(shù)據(jù)邏輯單元。現(xiàn)在不難理解了吧。
  2. value、descriptor中存儲(chǔ)數(shù)據(jù)的解析由Server的工程師決定,并無規(guī)范,雙發(fā)按照約定開發(fā)。
  3. Service/Characteristic均有一個(gè)唯一的UUID標(biāo)識(shí),UUID既有16位的也有128位的,我們需要了解的是16位的UUID是經(jīng)過藍(lán)牙組織認(rèn)證的,是需要購買的,當(dāng)然也有一些通用的16位UUID。
    例如Heart Rate服務(wù)的UUID就是0X180D,代碼中表示為0X00001800-0000-1000-8000-00805f9b34fb,其他位為固定的。而128位的UUID則可以自定義。
  4. GATT連接是獨(dú)占的。

應(yīng)用開發(fā)

添加權(quán)限

進(jìn)行藍(lán)牙APP的開發(fā),需要在manifest文件中加入如下的權(quán)限:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

BLUETOOTH權(quán)限使得你的APP可以使用藍(lán)牙的對(duì)話功能,例如建連和數(shù)據(jù)的傳輸。
BLUETOOTH_ADMIN權(quán)限允許APP啟動(dòng)設(shè)備的被發(fā)現(xiàn)以及操作藍(lán)牙的settings。
其他更詳細(xì)的查看官網(wǎng)上的說明BLE開發(fā)指南

獲得藍(lán)牙

要想進(jìn)行ble的開發(fā)首先要獲得設(shè)備上的藍(lán)牙適配器并保證藍(lán)牙是使能的,這樣才能進(jìn)一步的進(jìn)行ble的相關(guān)操作。

  1. 獲得藍(lán)牙適配器
    系統(tǒng)啟動(dòng)的時(shí)候藍(lán)牙相關(guān)的系統(tǒng)服務(wù)已經(jīng)開啟,這時(shí)候我們首先要獲得系統(tǒng)的藍(lán)牙服務(wù):
BluetoothManager bluetoothManager =
        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

通過藍(lán)牙的系統(tǒng)服務(wù)得到藍(lán)牙適配器:

BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

得到藍(lán)牙適配器之后,我們就能進(jìn)行藍(lán)牙的相關(guān)操作,無論是經(jīng)典藍(lán)牙還是ble都可以,當(dāng)然進(jìn)行這些操作之前我們首先使能藍(lán)牙。

  1. 藍(lán)牙的使能
    這個(gè)當(dāng)然是為了保證藍(lán)牙是開著的,給藍(lán)牙芯片使能。
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

這段代碼是調(diào)用了系統(tǒng)提供的開啟藍(lán)牙的對(duì)話框,點(diǎn)擊即可使能藍(lán)牙,其實(shí)本質(zhì)也是調(diào)用BluetoothAdapter.enable()。

  1. 掃描Ble設(shè)備
//1. Android 4.3以上,Android 5.0以下
mBluetoothAdapter.startLeScan(BluetoothAdapter.LeScanCallback LeScanCallback)
//2. Android 5.0以上,掃描的結(jié)果在mScanCallback中進(jìn)行處理
mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
mBluetoothLeScanner.startScan(ScanCallback mScanCallback);

注意傳入的callback參數(shù)是不同的。以下我們都按照5.0的API進(jìn)行。

  1. 得到掃描結(jié)果
    在掃描結(jié)果的callback函數(shù)中將掃描到的設(shè)備的名稱和地址進(jìn)行打印。
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            if(result != null){
                System.out.println("掃面到設(shè)備:" + result.getDevice().getName() + "  " + result.getDevice().getAddress()); 
            }
        }

因?yàn)閽呙璞旧硎莻€(gè)耗電操作,因此掃描到目標(biāo)設(shè)備后應(yīng)該立即體停止掃描

if(mTargetDeviceName.equal(result.getDevice().getName())){
        mBluetoothLeScanner.stopScan(mScanCallback);
}
  1. 對(duì)目標(biāo)設(shè)備進(jìn)行連接
result.getDevice().connectGatt(MainActivity.this, false, mGattCallback);

傳入的BluetoothGattCallback對(duì)象中對(duì)連接結(jié)果做處理,以及通過GATT進(jìn)行通信的絕大多數(shù)的操作都在這個(gè)對(duì)象中,至于后續(xù)BluetoothGattCallback的講解,我們將在demo以及后續(xù)的文章中進(jìn)行。

應(yīng)用demo之初識(shí)gatt

Android官網(wǎng)的例子中有BLE的示例,但是那個(gè)例子有些API已經(jīng)過時(shí),沒有使用最新的5.0的API,而且也寫得過于麻煩,不便于開發(fā)新手入門,因此我寫了一個(gè)簡單的demo,僅僅包含整個(gè)掃描、連接、獲取service的過程,一眼便能看懂,當(dāng)然這個(gè)demo的目的是增進(jìn)GATT的認(rèn)識(shí)。

Demo的下載地址:
** Github Jiesean : BleDemo **

運(yùn)行Demo并連接小米手環(huán)1代得到的結(jié)果如下:

Services num:6
掃描到Service:00001800-0000-1000-8000-00805f9b34fb
characteristic: 00002a00-0000-1000-8000-00805f9b34fb
characteristic: 00002a01-0000-1000-8000-00805f9b34fb
characteristic: 00002a02-0000-1000-8000-00805f9b34fb
characteristic: 00002a04-0000-1000-8000-00805f9b34fb
掃描到Service:00001801-0000-1000-8000-00805f9b34fb
characteristic: 00002a05-0000-1000-8000-00805f9b34fb
掃描到Service:0000fee0-0000-1000-8000-00805f9b34fb
characteristic: 0000ff01-0000-1000-8000-00805f9b34fb
characteristic: 0000ff02-0000-1000-8000-00805f9b34fb
characteristic: 0000ff03-0000-1000-8000-00805f9b34fb
characteristic: 0000ff04-0000-1000-8000-00805f9b34fb
characteristic: 0000ff05-0000-1000-8000-00805f9b34fb
characteristic: 0000ff06-0000-1000-8000-00805f9b34fb
characteristic: 0000ff07-0000-1000-8000-00805f9b34fb
characteristic: 0000ff08-0000-1000-8000-00805f9b34fb
characteristic: 0000ff09-0000-1000-8000-00805f9b34fb
characteristic: 0000ff0a-0000-1000-8000-00805f9b34fb
characteristic: 0000ff0b-0000-1000-8000-00805f9b34fb
characteristic: 0000ff0c-0000-1000-8000-00805f9b34fb
characteristic: 0000ff0d-0000-1000-8000-00805f9b34fb
characteristic: 0000ff0e-0000-1000-8000-00805f9b34fb
characteristic: 0000ff0f-0000-1000-8000-00805f9b34fb
characteristic: 0000ff10-0000-1000-8000-00805f9b34fb
掃描到Service:0000fee1-0000-1000-8000-00805f9b34fb
characteristic: 0000fedd-0000-1000-8000-00805f9b34fb
characteristic: 0000fede-0000-1000-8000-00805f9b34fb
characteristic: 0000fedf-0000-1000-8000-00805f9b34fb
characteristic: 0000fed0-0000-1000-8000-00805f9b34fb
characteristic: 0000fed1-0000-1000-8000-00805f9b34fb
characteristic: 0000fed2-0000-1000-8000-00805f9b34fb
characteristic: 0000fed3-0000-1000-8000-00805f9b34fb
掃描到Service:0000fee7-0000-1000-8000-00805f9b34fb
characteristic: 0000fec7-0000-1000-8000-00805f9b34fb
characteristic: 0000fec8-0000-1000-8000-00805f9b34fb
characteristic: 0000fec9-0000-1000-8000-00805f9b34fb
掃描到Service:00001802-0000-1000-8000-00805f9b34fb
characteristic: 00002a06-0000-1000-8000-00805f9b34fb

我們可以看到總共得到了6個(gè)Service,分別是:

下一篇文章我們將對(duì)小米手環(huán)進(jìn)行讀取和操作。

<p>

** 相關(guān)閱讀: **
** BLE簡介 **
** 低功耗藍(lán)牙BLE協(xié)議棧簡介 **

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,024評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,328評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,878評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,098評(píng)論 0 286
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,616評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,554評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,725評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,971評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評(píng)論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,339評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,695評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容