Android Bluetooth藍(lán)牙技術(shù)使用流程詳解
在上篇文章給大家介紹了Android Bluetooth藍(lán)牙技術(shù)初體驗(yàn)相關(guān)內(nèi)容,感興趣的朋友可以點(diǎn)擊了解詳情。
一:藍(lán)牙設(shè)備之間的通信主要包括了四個(gè)步驟
設(shè)置藍(lán)牙設(shè)備
尋找局域網(wǎng)內(nèi)可能或者匹配的設(shè)備
連接設(shè)備
設(shè)備之間的數(shù)據(jù)傳輸
二:具體編程實(shí)現(xiàn)
1. 啟動(dòng)藍(lán)牙功能
首先通過(guò)調(diào)用靜態(tài)方法getDefaultAdapter()獲取藍(lán)牙適配器BluetoothAdapter,如果返回為空,則無(wú)法繼續(xù)執(zhí)行了。例如:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { // Device does not support Bluetooth }
其次,調(diào)用isEnabled()來(lái)查詢(xún)當(dāng)前藍(lán)牙設(shè)備的狀態(tài),如果返回為false,則表示藍(lán)牙設(shè)備沒(méi)有開(kāi)啟,接下來(lái)你需要封裝一個(gè)ACTION_REQUEST_ENABLE請(qǐng)求到intent里面,調(diào)用startActivityForResult()方法使能藍(lán)牙設(shè)備,例如:
if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
2. 查找設(shè)備
使用BluetoothAdapter類(lèi)里的方法,你可以查找遠(yuǎn)端設(shè)備(大概十米以?xún)?nèi))或者查詢(xún)?cè)谀闶謾C(jī)上已經(jīng)匹配(或者說(shuō)綁定)的其他設(shè)備了。當(dāng)然需要確定對(duì)方藍(lán)牙設(shè)備已經(jīng)開(kāi)啟或者已經(jīng)開(kāi)啟了“被發(fā)現(xiàn)使能”功能(對(duì)方設(shè)備是可以被發(fā)現(xiàn)的是你能夠發(fā)起連接的前提條件)。如果該設(shè)備是可以被發(fā)現(xiàn)的,會(huì)反饋回來(lái)一些對(duì)方的設(shè)備信息,比如名字、MAC地址等,利用這些信息,你的設(shè)備就可以選擇去向?qū)Ψ匠跏蓟粋€(gè)連接。
如果你是第一次與該設(shè)備連接,那么一個(gè)配對(duì)的請(qǐng)求就會(huì)自動(dòng)的顯示給用戶(hù)。當(dāng)設(shè)備配對(duì)好之后,他的一些基本信息(主要是名字和MAC)被保存下來(lái)并可以使用藍(lán)牙的API來(lái)讀取。使用已知的MAC地址就可以對(duì)遠(yuǎn)端的藍(lán)牙設(shè)備發(fā)起連接請(qǐng)求。
匹配好的設(shè)備和連接上的設(shè)備的不同點(diǎn):匹配好只是說(shuō)明對(duì)方設(shè)備發(fā)現(xiàn)了你的存在,并擁有一個(gè)共同的識(shí)別碼,并且可以連接。連接上:表示當(dāng)前設(shè)備共享一個(gè)RFCOMM信道并且兩者之間可以交換數(shù)據(jù)。也就是是說(shuō)藍(lán)牙設(shè)備在建立RFCOMM信道之前,必須是已經(jīng)配對(duì)好了的。
3. 查詢(xún)匹配好的設(shè)備
在建立連接之前你必須先查詢(xún)配對(duì)好了的藍(lán)牙設(shè)備集以便選取一個(gè)設(shè)備進(jìn)行通信,例如你可以你可以查詢(xún)所有配對(duì)的藍(lán)牙設(shè)備,并使用一個(gè)數(shù)組適配器將其打印顯示出來(lái):
Set<BluetoothDevice> pairedDevices =mBluetoothAdapter.getBondedDevices(); // If there are paired devices if (pairedDevices.size() > 0) { //Loop through paired devices for (BluetoothDevice device : pairedDevices) { // Add the name and address to an array adapter to show in a ListView mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } }
建立一個(gè)藍(lán)牙連接只需要MAC地址就已經(jīng)足夠。
4. 掃描設(shè)備
掃描設(shè)備,只需要調(diào)用startDiscovery()方法,這個(gè)掃描的過(guò)程大概持續(xù)是12秒,應(yīng)用程序?yàn)榱薃CTION_FOUND動(dòng)作需要注冊(cè)一個(gè)BroadcastReceiver來(lái)接受設(shè)備掃描到的信息。對(duì)于每一個(gè)設(shè)備,系統(tǒng)都會(huì)廣播ACTION_FOUND動(dòng)作。
// 用ACTION_FOUND為action注冊(cè)廣播接收器 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // 發(fā)現(xiàn)設(shè)備 if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 從Intent中獲取藍(lán)牙設(shè)備 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 添加名字和地址到設(shè)備適配器中 mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } } }; //注冊(cè)廣播接收器 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mReceiver, filter); //在onDestroy時(shí)記得注銷(xiāo)廣播接收器
5. 使能被發(fā)現(xiàn)
如果你想使你的設(shè)備能夠被其他設(shè)備發(fā)現(xiàn),將ACTION_REQUEST_DISCOVERABLE動(dòng)作封裝在intent中并調(diào)用startActivityForResult(Intent, int)方法就可以了。它將在不使你應(yīng)用程序退出的情況下使你的設(shè)備能夠被發(fā)現(xiàn)。缺省情況下的使能時(shí)間是120秒,當(dāng)然你可以可以通過(guò)添加EXTRA_DISCOVERABLE_DURATION字段來(lái)改變使能時(shí)間(最大不超過(guò)300秒)例如:
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent);
運(yùn)行該段代碼之后,系統(tǒng)會(huì)彈出一個(gè)對(duì)話(huà)框來(lái)提示你啟動(dòng)設(shè)備使能被發(fā)現(xiàn)(此過(guò)程中如果你的藍(lán)牙功能沒(méi)有開(kāi)啟,系統(tǒng)會(huì)幫你開(kāi)啟),并且如果你準(zhǔn)備對(duì)該遠(yuǎn)端設(shè)備發(fā)現(xiàn)一個(gè)連接,你不需要開(kāi)啟設(shè)備被發(fā)現(xiàn)功能,因?yàn)樵摴δ苤皇窃谀愕膽?yīng)用程序作為服務(wù)器端的時(shí)候才需要。
6. 連接設(shè)備
在應(yīng)用程序中,想建立兩個(gè)藍(lán)牙設(shè)備之間的連接,必須實(shí)現(xiàn)客戶(hù)端和服務(wù)器端的代碼(因?yàn)槿魏我粋€(gè)設(shè)備都必須可以作為服務(wù)端或者客戶(hù)端)。一個(gè)開(kāi)啟服務(wù)來(lái)監(jiān)聽(tīng),一個(gè)發(fā)起連接請(qǐng)求(使用服務(wù)器端設(shè)備的MAC地址)。當(dāng)他們都擁有一個(gè)藍(lán)牙套接字在同一RFECOMM信道上的時(shí)候,可以認(rèn)為他們之間已經(jīng)連接上了。服務(wù)端和客戶(hù)端通過(guò)不同的方式或其他們的藍(lán)牙套接字。當(dāng)一個(gè)連接監(jiān)聽(tīng)到的時(shí)候,服務(wù)端獲取到藍(lán)牙套接字。當(dāng)客戶(hù)可打開(kāi)一個(gè)FRCOMM信道給服務(wù)器端的時(shí)候,客戶(hù)端獲取到藍(lán)牙套接字。
注意:在此過(guò)程中,如果兩個(gè)藍(lán)牙設(shè)備還沒(méi)有配對(duì)好的,android系統(tǒng)會(huì)通過(guò)一個(gè)通知或者對(duì)話(huà)框的形式來(lái)通知用戶(hù)。RFCOMM連接請(qǐng)求會(huì)在用戶(hù)選擇之前阻塞。
7. 服務(wù)端的連接
當(dāng)你想要連接兩臺(tái)設(shè)備時(shí),一個(gè)必須作為服務(wù)端(通過(guò)持有一個(gè)打開(kāi)的BluetoothServerSocket),目的是監(jiān)聽(tīng)外來(lái)連接請(qǐng)求,當(dāng)監(jiān)聽(tīng)到以后提供一個(gè)連接上的BluetoothSocket給客戶(hù)端,當(dāng)客戶(hù)端從BluetoothServerSocket得到BluetoothSocket以后就可以銷(xiāo)毀BluetoothServerSocket,除非你還想監(jiān)聽(tīng)更多的連接請(qǐng)求。
建立服務(wù)套接字和監(jiān)聽(tīng)連接的基本步驟:
首先通過(guò)調(diào)用listenUsingRfcommWithServiceRecord(String, UUID)方法來(lái)獲取BluetoothServerSocket對(duì)象,參數(shù)String代表了該服務(wù)的名稱(chēng),UUID代表了和客戶(hù)端連接的一個(gè)標(biāo)識(shí)(128位格式的字符串ID,相當(dāng)于PIN碼),UUID必須雙方匹配才可以建立連接。
其次調(diào)用accept()方法來(lái)監(jiān)聽(tīng)可能到來(lái)的連接請(qǐng)求,當(dāng)監(jiān)聽(tīng)到以后,返回一個(gè)連接上的藍(lán)牙套接字BluetoothSocket。
最后,在監(jiān)聽(tīng)到一個(gè)連接以后,需要調(diào)用close()方法來(lái)關(guān)閉監(jiān)聽(tīng)程序。(一般藍(lán)牙設(shè)備之間是點(diǎn)對(duì)點(diǎn)的傳輸)
注意:accept()方法不應(yīng)該放在主Acitvity里面,因?yàn)樗且环N阻塞調(diào)用(在沒(méi)有監(jiān)聽(tīng)到連接請(qǐng)求之前程序就一直停在那里)。解決方法是新建一個(gè)線(xiàn)程來(lái)管理。例如:
8. 客戶(hù)端的連接
為了初始化一個(gè)與遠(yuǎn)端設(shè)備的連接,需要先獲取代表該設(shè)備的一個(gè)BluetoothDevice對(duì)象。通過(guò)BluetoothDevice對(duì)象來(lái)獲取BluetoothSocket并初始化連接,具體步驟:
使用BluetoothDevice對(duì)象里的方法createRfcommSocketToServiceRecord(UUID)來(lái)獲取BluetoothSocket。UUID就是匹配碼。然后,調(diào)用connect()方法來(lái)。如果遠(yuǎn)端設(shè)備接收了該連接,他們將在通信過(guò)程中共享RFFCOMM信道,并且connect返回。
注意:conncet()方法也是阻塞調(diào)用,一般建立一個(gè)獨(dú)立的線(xiàn)程中來(lái)調(diào)用該方法。在設(shè)備discover過(guò)程中不應(yīng)該發(fā)起連接connect(),這樣會(huì)明顯減慢速度以至于連接失敗。且數(shù)據(jù)傳輸完成只有調(diào)用close()方法來(lái)關(guān)閉連接,這樣可以節(jié)省系統(tǒng)內(nèi)部資源。
9. 管理連接
當(dāng)設(shè)備連接上以后,每個(gè)設(shè)備都擁有各自的BluetoothSocket。就可以實(shí)現(xiàn)設(shè)備之間數(shù)據(jù)的共享了。
首先通過(guò)調(diào)用getInputStream()和getOutputStream()方法來(lái)獲取輸入輸出流。
然后通過(guò)調(diào)用read(byte[]) 和write(byte[]).方法來(lái)讀取或者寫(xiě)數(shù)據(jù)。
實(shí)現(xiàn)細(xì)節(jié):以為讀取和寫(xiě)操作都是阻塞調(diào)用,需要建立一個(gè)專(zhuān)用線(xiàn)程來(lái)管理。
10. 權(quán)限設(shè)置
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permissionandroid:name="android.permission.BLUETOOTH" />
以上所述是小編給大家分享的Android Bluetooth藍(lán)牙技術(shù)使用流程詳解,希望對(duì)大家有所幫助。
- Android藍(lán)牙開(kāi)發(fā)深入解析
- 詳解Android——藍(lán)牙技術(shù) 帶你實(shí)現(xiàn)終端間數(shù)據(jù)傳輸
- Android單片機(jī)與藍(lán)牙模塊通信實(shí)例代碼
- 分享Android 藍(lán)牙4.0(ble)開(kāi)發(fā)的解決方案
- Android 獲取藍(lán)牙Mac地址的正確方法
- Android手機(jī)通過(guò)藍(lán)牙連接佳博打印機(jī)的實(shí)例代碼
- android實(shí)現(xiàn)藍(lán)牙文件發(fā)送的實(shí)例代碼,支持多種機(jī)型
- Android實(shí)現(xiàn)藍(lán)牙(BlueTooth)設(shè)備檢測(cè)連接
- 詳解Android 藍(lán)牙通信方式總結(jié)
- Android學(xué)習(xí)筆記之藍(lán)牙功能
相關(guān)文章
微信瀏覽器彈出框滑動(dòng)時(shí)頁(yè)面跟著滑動(dòng)的實(shí)現(xiàn)代碼(兼容Android和IOS端)
小編在做微信開(kāi)發(fā)的時(shí)候遇到微信瀏覽器彈出框滑動(dòng)時(shí)頁(yè)面跟著滑動(dòng)的效果,下面把關(guān)鍵代碼分享給大家,需要的朋友參考下2016-11-11android開(kāi)發(fā)修改狀態(tài)欄背景色和圖標(biāo)顏色的示例
本篇文章主要介紹了android開(kāi)發(fā)修改狀態(tài)欄背景色和圖標(biāo)顏色的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01Android Studio自動(dòng)生成UML關(guān)系圖的方法步驟
本文主要介紹了Android Studio自動(dòng)生成UML關(guān)系圖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08解決Android Studio突然不顯示logcat日志的問(wèn)題
這篇文章主要介紹了解決Android Studio突然不顯示logcat日志的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04仿墨跡天氣在Android App中實(shí)現(xiàn)自定義zip皮膚更換
這篇文章主要介紹了仿墨跡天氣在Android App中實(shí)現(xiàn)自定義zip皮膚更換的方法,即讓用戶(hù)可以自行通過(guò)自制或者下載的zip皮膚包進(jìn)行換膚,需要的朋友可以參考下2016-02-02