通過藍(lán)牙傳輸數(shù)據(jù)與Socket類似。在網(wǎng)絡(luò)中使用Socket和ServerSocket控制客戶端和服務(wù)端的數(shù)據(jù)讀寫。而藍(lán)牙通訊也由客戶端和服務(wù)端Socket來完成。藍(lán)牙客戶端Socket是BluetoothSocket,藍(lán)牙服務(wù)端Socket是BluetoothServerSocket。這兩個類都在android.bluetooth包中。
創(chuàng)新互聯(lián)公司長期為近1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為沭陽企業(yè)提供專業(yè)的網(wǎng)站設(shè)計、網(wǎng)站制作,沭陽網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
如果打算建議兩個藍(lán)牙設(shè)備之間的連接,則必須實現(xiàn)服務(wù)器端與客戶端的機制。當(dāng)兩個設(shè)備在同一個RFCOMM channel下分別擁有一個連接的BluetoothSocket,這兩個設(shè)備才可以說是建立了連接。
服務(wù)器設(shè)備與客戶端設(shè)備獲取BluetoothSocket的途徑是不同的。服務(wù)器設(shè)備是通過accepted一個incoming connection來獲取的,而客戶端設(shè)備則是通過打開一個到服務(wù)器的RFCOMMchannel來獲取的。
通過調(diào)用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID) 方法來獲取
BluetoothServerSocket(UUID用于客戶端與服務(wù)器端之間的配對)調(diào)用BluetoothServerSocket的 accept() 方法監(jiān)聽連接請求,如果收到請求,則返回一個BluetoothSocket實例。
如果不想在accept其他的連接,則調(diào)用BluetoothServerSocket的 close() 方法釋放資源(調(diào)用該方法后,之前獲得的BluetoothSocket實例并沒有close。但由于RFCOMM一個時刻只允許在一條channel中有一個連接,則一般在accept一個連接后,便close掉BluetoothServerSocket)
通過搜索得到服務(wù)器端的BluetoothService,調(diào)用BluetoothService的listenUsingRfcommWithServiceRecord(String, UUID)方法獲取BluetoothSocket(該UUID應(yīng)該同于服務(wù)器端的UUID)。
調(diào)用BluetoothSocket的 connect() 方法(該方法為block方法),如果UUID同服務(wù)器端的UUID匹配,并且連接被服務(wù)器端accept,則 connect() 方法返回。
藍(lán)牙設(shè)備在連接前,會先檢查設(shè)備是否已經(jīng)配對過,如果沒有則先配對,配對完成后,再開始連接。
藍(lán)牙連接開始于設(shè)備列表 DeviceListPreferenceFragment的onPreferenceTreeClick方法。
DeviceListPreferenceFragment是藍(lán)牙設(shè)備列表,點擊其中一個藍(lán)牙設(shè)備,開始藍(lán)牙的連接過程。
調(diào)用onDevicePreferenceClick方法,接著調(diào)用BluetoothDevicePreference的onClicked方法,開始連接,以及連接前的狀態(tài)檢測。
獲取mCachedDevice的綁定狀態(tài),
pair方法會調(diào)用CachedBluetoothDevice.startPairing,啟動配對
createBond調(diào)用BluetoothDevice.createBond方法,BluetoothDevice.createBond接著調(diào)用IBluetooth.createBond方法,下面會調(diào)用藍(lán)牙遠(yuǎn)程服務(wù)。
和藍(lán)牙掃描一樣,實現(xiàn)IBluetooth接口的類是AdapterServiceBinder,
AdapterServiceBinder實現(xiàn)IBluetooth.Stub接口,并且是AdapterService的私有內(nèi)部類, AdapterServiceBinder接受事件,都會轉(zhuǎn)交AdapterService處理 ,所以IBluetooth.createBond方法會調(diào)用AdapterService.createBond方法。
createBond方法會檢查一下遠(yuǎn)程設(shè)備屬性信息,再次取消藍(lán)牙掃描任務(wù),將配對任務(wù)轉(zhuǎn)交mBondStateMachine,由狀態(tài)機處理該信息。
BondStateMachine狀態(tài)機的初始狀態(tài)是StableState,所以BondStateMachine.CREATE_BOND由StableState處理,StableState在processMessage中調(diào)用BondStateMachine.createBond方法
createBondNative方法實現(xiàn)com_android_bluetooth_btservice_AdapterService.cpp中
普通藍(lán)牙設(shè)備官方文檔
Android 平臺包含藍(lán)牙網(wǎng)絡(luò)堆棧支持 ,憑借此支持,設(shè)備能以無線方式與其他藍(lán)牙設(shè)備交換數(shù)據(jù)。應(yīng)用框架提供了通過 Android Bluetooth API 訪問藍(lán)牙功能的途徑。使用 Bluetooth API Android 應(yīng)用可以執(zhí)行下面的操作:
傳統(tǒng)藍(lán)牙適用于電池使用強度較大的操作,例如 Android 設(shè)備之間的流傳輸和通信等。針對具有低功耗要求的藍(lán)牙設(shè)備,Android 4.3(API 18)中引入了面向低功耗藍(lán)牙的 API 支持。
使用 Android Bluetooth API 來完成使用藍(lán)牙進(jìn)行通信的四項主要任務(wù): 設(shè)置藍(lán)牙 、 查找局部區(qū)域內(nèi)的配對設(shè)備或可用設(shè)備 、 連接設(shè)備 ,以及在 設(shè)備之間傳輸數(shù)據(jù) 。
關(guān)于藍(lán)牙的 API 在 android.bluetooth 包中,下面介紹一下和藍(lán)牙相關(guān)的主要類:
在 BluetoothProfile IPC 客戶端連接到服務(wù)(即,運行特定配置文件的內(nèi)部服務(wù))或斷開服務(wù)連接時向其發(fā)送通知的接口。
使用藍(lán)牙必須聲明權(quán)限 BLUETOOTH 才可以執(zhí)行藍(lán)牙通信。
1、獲取藍(lán)牙適配器
例如:我們可以查詢所有已配對的設(shè)備,然后使用 ArrayAdapter 向用戶顯示每臺設(shè)備的名稱:
要發(fā)起連接僅需要知道目標(biāo)藍(lán)牙設(shè)備的 Mac 地址就可以了。
注意 執(zhí)行 discovery 對于藍(lán)牙適配器來說是一個非常繁重的過程,并且會消耗大量資源。在找到要連接的設(shè)備后, 要確保使用 cancelDiscovery() 來停止發(fā)現(xiàn),然后嘗試連接 。如果您已經(jīng)和某臺設(shè)備進(jìn)行連接,那么這個時候執(zhí)行發(fā)現(xiàn)操作會大幅度的減少此連接可用的帶寬!因此不應(yīng)該在處于連接狀態(tài)的時候執(zhí)行發(fā)現(xiàn)操作!
例如:
在連接之前如果兩個設(shè)備沒有配對,則系統(tǒng)會自動發(fā)出配對請求。
服務(wù)器套接字接受連接的基本過程
放在子線程中去執(zhí)行。
例子:
客戶端連接的基本過程
調(diào)用 connect() 的時候要確??蛻舳藳]有執(zhí)行發(fā)現(xiàn)操作。如果執(zhí)行了會大幅度降低連接的速度,增加失敗的可能。
例子
在連接之前調(diào)用 cancleDiscovery() 在進(jìn)行連接之前應(yīng)該始終調(diào)用這個方法,而且調(diào)用的時候無需檢測是否正在掃描。
過程:
從 Android 3.0 開始, Bluetooth API 便支持使用藍(lán)牙配置文件。藍(lán)牙配置文件是適用于設(shè)備間藍(lán)牙通信的無線接口規(guī)范。
1、藍(lán)牙配置文件就是設(shè)備間通信(藍(lán)牙設(shè)備)的一種規(guī)范
免提配置文件便是一個示例,對于連接到無線耳機的手機,兩臺設(shè)備都必須支持免提配置文件。我們也可以通過實現(xiàn)接口 BluetoothProfile 來寫入自己的類來支持特定的藍(lán)牙配置文件。Android API 提供了以下的幾種藍(lán)牙配置文件的實現(xiàn):
2、使用配置文件的基本步驟
創(chuàng)建 HDP 應(yīng)用:
關(guān)于普通藍(lán)牙設(shè)備和普通藍(lán)牙設(shè)備之間的連接通信
關(guān)于藍(lán)牙設(shè)備和藍(lán)牙儀器(藍(lán)牙耳機、電子秤等等類似產(chǎn)品)
這種之間的通信是通過配置文件代理來實現(xiàn)的。
都有一個對應(yīng)的配置文件代理類。具體的操作是通過這個對象來完成。
參考: ;mid=2247484128idx=1sn=9d59b9ad66fb68b9569c29566103c009scene=21#wechat_redirect
前面的兩篇文章,主要是在 Android 官網(wǎng)關(guān)于藍(lán)牙介紹的基礎(chǔ)上加上自己的理解完成的。主要針對的是 Android 開發(fā)中的一些 API 的使用。
第一篇文章 Android 藍(lán)牙開發(fā)(一) 主要是介紹了普通的藍(lán)牙在 Android 開發(fā)中的運用。
第二篇文章 Android 藍(lán)牙開發(fā)(二) 主要是介紹了低功耗藍(lán)牙的開發(fā)。
這篇文章主要介紹的是藍(lán)牙的歷史和一些關(guān)于藍(lán)牙的通用知識,還有廣播包的知識。要想徹底了解藍(lán)牙開發(fā),這些基礎(chǔ)的知識也是需要的,就像網(wǎng)絡(luò)協(xié)議一樣,這些都是基礎(chǔ)的內(nèi)容。我們的 API 的調(diào)用都是以這個為基礎(chǔ)的,了解這些,開發(fā)過程中遇到問題,才可以知道什么怎么一回事。
下篇文章主要講的就是實際開發(fā)中的一些坑。
藍(lán)牙其實就是一種近距離無線通信技術(shù)。
從下到上分別為:控制器(Controller)--主機(host)--應(yīng)用(Application)
詳細(xì)介紹各個層的含義:
BLE 應(yīng)用可以分為兩大類:基于非連接的和基于連接的
意思就是外設(shè)和周邊設(shè)備不發(fā)生連接,主要靠掃描到的廣播來獲取信息。發(fā)送廣播的一方叫做 broadcaster 監(jiān)聽廣播的一方叫做 oberver 在 GAP 層有對應(yīng)的角色定義。
網(wǎng)絡(luò)拓?fù)鋱D:
這種方式就是廣播設(shè)備不斷的向外發(fā)送廣播(含有特定的信息),然后觀察者接受到廣播按照兩者之間約定好的協(xié)議進(jìn)行解析拿到有用的信息。例如:iBeacon,通過這種設(shè)備我們可以實現(xiàn)室內(nèi)定位。
其實這些設(shè)備的角色可以即使廣播者又是觀察者。接收到廣播后作出了處理,然后又發(fā)送廣播。這樣就形成了雙向的網(wǎng)絡(luò),類似于因特網(wǎng),這就是藍(lán)牙 Mesh 組網(wǎng)。
廣播數(shù)據(jù)包格式:
每個廣播數(shù)據(jù)包由 31 byte 組成。分為有效數(shù)據(jù)和無效數(shù)據(jù)兩部分。
例子:
這里是掃描的數(shù)據(jù)包(轉(zhuǎn)換成了 16 進(jìn)制,兩個代表一個字節(jié)),第一個字節(jié)是 02 表示后面的兩個字節(jié)是數(shù)據(jù)部分,然后第二個字節(jié)是 01 表示了數(shù)據(jù)的類型。后面一個字節(jié)就是真正的數(shù)據(jù)了。這個廣播數(shù)據(jù)單元就分析完了。下面就是另一個數(shù)據(jù)單元了。依次類推,關(guān)于數(shù)據(jù)類型的解釋,官網(wǎng)有。
這是數(shù)據(jù)類型對應(yīng)的含義表。
網(wǎng)絡(luò)拓?fù)鋱D:
一個中心設(shè)備可連接多個外設(shè),但是一個外設(shè)只能連接一個中心(外設(shè)連接成功后就會停止對外廣播,別人就發(fā)現(xiàn)不了它了)。其中一個中心設(shè)備的連接外設(shè)的數(shù)量也是有限的。
鏈接: ;mid=2247484141idx=1sn=fd7e71864189b3631ce529afeb4cf669scene=21#wechat_redirect
若使用的是vivo手機,進(jìn)入手機設(shè)置--(其他網(wǎng)絡(luò)與連接/更多設(shè)置)--藍(lán)牙--開啟藍(lán)牙,開啟后手機會自動搜索附近的設(shè)備,點擊設(shè)備名就可以配對了,配對成功之后,進(jìn)入文件管理中找到需要傳輸?shù)奈募L按,選擇使用“藍(lán)牙”分享即可。
在上一篇中有介紹了Wifi與網(wǎng)絡(luò)連接處理
Android開發(fā)之WiFi與網(wǎng)絡(luò)連接處理
下面,來繼續(xù)說說Android中藍(lán)牙的基本使用。
Bluetooth是目前使用的最廣泛的無線通訊協(xié)議之一,主要針對短距離設(shè)備通訊(10米),常用于連接耳機、鼠標(biāo)和移動通訊設(shè)備等。
值得一提的是:
android4.2新增了部分新功能,但是對于Bluetooth熟悉的人或許開始頭疼了,那就是Android4.2引入了一個新的藍(lán)牙協(xié)議棧針BLE。谷歌和Broadcom之間的合作,開發(fā)新的藍(lán)牙協(xié)議棧,取代了基于堆棧的Bluez。因此市場上出現(xiàn)了老設(shè)備的兼容問題,很多藍(lán)牙設(shè)備在android4.2手機上不能正常使用。
BluetoothAdapter簡單點來說就是代表了本設(shè)備(手機、電腦等)的藍(lán)牙適配器對象。
first:we need permission
要操作藍(lán)牙,先要在AndroidManifest.xml里加入權(quán)限
**下面來看看如何使用藍(lán)牙。 **↓↓↓****
Demo已就緒:
返回值:如果設(shè)備具備藍(lán)牙功能,返回BluetoothAdapter 實例;否則,返回null對象。
打開藍(lán)牙設(shè)備的方式:
1.直接調(diào)用函數(shù)enable()去打開藍(lán)牙設(shè)備 ;
2.系統(tǒng)API去打開藍(lán)牙設(shè)備,該方式會彈出一個對話框樣式的Activity供用戶選擇是否打開藍(lán)牙設(shè)備。
注意: 1.如果藍(lán)牙已經(jīng)開啟,不會彈出該Activity界面。2.在目前大多數(shù)Android手機中,是不支持在飛行模式下開啟藍(lán)牙的。如果藍(lán)牙已經(jīng)開啟,那么藍(lán)牙的開關(guān) ,狀態(tài)會隨著飛行模式的狀態(tài)而發(fā)生改變。
1. 搜索藍(lán)牙設(shè)備
使用BluetoothAdapter的startDiscovery()方法來搜索藍(lán)牙設(shè)備
startDiscovery()方法是一個異步方法,調(diào)用后會立即返回。該方法會進(jìn)行對其他藍(lán)牙設(shè)備的搜索,該過程會持續(xù)12秒。該方法調(diào)用后,搜索過程實際上是在一個System Service中進(jìn)行的,所以可以調(diào)用cancelDiscovery()方法來停止搜索(該方法可以在未執(zhí)行discovery請求時調(diào)用)。
系統(tǒng)開始搜索藍(lán)牙設(shè)備
^( *  ̄(oo) ̄ ) ^ 系統(tǒng)會發(fā)送以下三個廣播:
2.掃描設(shè)備
3.定義廣播接收器接收搜索結(jié)果
4.注冊廣播
獲取附近的藍(lán)牙設(shè)備
第一步建立連接:首先Android sdk(2.0以上版本)支持的藍(lán)牙連接是通過BluetoothSocket建立連接,服務(wù)端BluetoothServerSocket和客戶端(BluetoothSocket)需指定同樣的UUID,才能建立連接,因為建立連接的方法會阻塞線程,所以服務(wù)器端和客戶端都應(yīng)啟動新線程連接。
(這里的服務(wù)端和客戶端是相對來說的)
兩個藍(lán)牙設(shè)備之間的連接,則必須實現(xiàn)服務(wù)端與客戶端的機制。
當(dāng)兩個設(shè)備在同一個RFCOMM channel下分別擁有一個連接的BluetoothSocket,這兩個設(shè)備才可以說是建立了連接。
服務(wù)端設(shè)備與客戶端設(shè)備獲取BluetoothSocket的途徑是不同的。
1,服務(wù)端設(shè)備是通過accepted一個incoming connection來獲取的,
2,客戶端設(shè)備則是通過打開一個到服務(wù)端的RFCOMM channel來獲取的。
服務(wù)端
通過調(diào)用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法來獲取BluetoothServerSocket(UUID用于客戶端與服務(wù)端之間的配對)
客戶端
調(diào)用BluetoothService的createRfcommSocketToServiceRecord(UUID)方法獲取BluetoothSocket(該UUID應(yīng)該同于服務(wù)端的UUID)。
調(diào)用BluetoothSocket的connect()方法(該方法為block方法),如果UUID同服務(wù)端的UUID匹配,并且連接被服務(wù)端accept,則connect()方法返回。
數(shù)據(jù)傳遞,通過以上操作,就已經(jīng)建立的BluetoothSocket連接了,數(shù)據(jù)傳遞無非是通過流的形式
獲取流
該類就是關(guān)于遠(yuǎn)程藍(lán)牙設(shè)備的一個描述。通過它可以和本地藍(lán)牙設(shè)備---BluetoothAdapter連接通信。
好多東西我也不知道怎么描述,下面給出Demo:
剛好有剛學(xué)習(xí)的小伙伴問我ListView怎么用,那我就用ListView。
源碼:
RairDemo
GitHub:
Coding: