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