Android-藍芽聊天demo
Android 中將藍芽分為傳統藍芽和低功耗藍芽(Bluetooth low energy)兩種。後者的優勢在於快速搜尋,快速連線,超低功耗保持連線和資料傳輸,同時低功耗帶來的缺點是資料傳輸速率低,所以多用在可穿戴式裝置。
在這裡我們主要介紹使用傳統藍芽來實現一個聊天的資料傳輸 demo。以下內容基本都是基於官方文件的二次闡述,以及一些疑惑的查詢到的解答,最後在 demo 裡面有對藍芽的相關操作進行了封裝。先貼個圖看看效果吧:
藍芽.png
基礎知識
BluetoothAdapter: 本地藍芽介面卡,我們在發現裝置,配對的時候都得用上它。
BluetoothDevice: 遠端藍芽裝置,就是代表著你可以連線的一個裝置,裡面儲存名字,MAC地址等資訊。
BluetoothSocket 和 BluetoothServerSocket: 藍芽套接字,和 TCP 的 Socket 相似。一臺裝置開啟一個 ServerSocket 並監聽,另一臺裝置開啟 Socket 進行連線,以此實現一個端對端的連線和資料傳輸。
UUID: 唯一識別符。它被用於唯一標識應用的藍芽服務(不是表示藍芽裝置)。
Q1:為什麼網上的大多數例子都是使用
00001101-0000-1000-8000-00805F9B34FB
這個UUID?
A1:這是因為一個藍芽裝置裡面可以提供諸多服務,如A2DP
(藍芽音訊傳輸)、HEADFREE
(擴音)、SPP
(串列埠通訊) 等等。而上面的字串碼就是 SPP 的 UUID,基本藍芽板上預設就是這個值,我們可以透過UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
來將字串轉成 UUID。
在連線藍芽串列埠板我們往往就會使用上面的UUID,但是如果 Android 端對端的話,建議自己自己設定 UUID,這樣別人的 UUID 就連不上了。
實現一個藍芽聊天demo
要實現一個藍芽聊天demo,首先我們有兩臺有藍芽功能的裝置,這裡我用了兩臺手機。按照流程一般來說要開啟藍芽-搜尋裝置-配對裝置-連線-通訊。如此就能實現一個基本的藍芽通訊。
第一步:許可權
在 Android 中沒有許可權寸步難行。要使用藍芽,還需要宣告相應的許可權。
<manifest ... > <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> ...</manifest>
BLUETOOTH 是基本的許可權,用於你的藍芽連線,資料傳輸等。
BLUETOOTH_ADMIN 一般應只用於發現本地藍芽裝置。
除非該應用是將要應使用者請求修改藍芽設定的“超級管理員”,否則不應使用此許可權所授予的其他能力。
另:如果要使用
BLUETOOTH_ADMIN
許可權,則還必須擁有BLUETOOTH
許可權。
此外會發現我這裡比官方文件還多了個 ACCESS_COARSE_LOCATION,這是因為我在實測過程中,我的測試機Android 8.0 系統中,藍芽掃描沒有掃描出資訊,但是系統是有的。在網上一番尋找之後發現在 Android 6.0 之後還需要一個模糊定位的許可權,否則掃描功能無效。
:為給使用者提供更嚴格的資料保護,從此版本(6.0)開始,對於使用 WLAN API 和 Bluetooth API 的應用,Android 移除了對裝置本地硬體識別符號的程式設計訪問權。
WifiInfo.getMacAddress()
方法和BluetoothAdapter.getAddress()
方法現在會返回常量值02:00:00:00:00:00
。
現在,要透過藍芽和 WLAN 掃描訪問附近外部裝置的硬體識別符號,您的應用必須擁有ACCESS_FINE_LOCATION
或ACCESS_COARSE_LOCATION
許可權。
關於動態許可權申請在此不作累述,小夥伴們可以自己去實現。
第二步:啟動藍芽
1、獲取 BluetoothAdapter
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) { //TODO 裝置不支援藍芽,阻斷使用者操作}
2、啟動藍芽
if(!mBlueAdapter.isEnabled()){ //請求藍芽 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
系統將會彈窗提示使用者是否開啟藍芽,使用者的選擇將在 onActivityResult() 中得到反饋。同意的時候收到 RESULT_OK,拒絕的時候收到 RESULT_CANCELED。
第三步:查詢裝置
1、查詢已配對裝置
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();// If there are paired devicesif (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()); } }
2、查詢未知裝置
mBlueAdapter.startDiscovery()
查詢未知裝置只需要呼叫 startDiscovery() 即可,這是一個非同步操作,系統一般會在後臺程式進行一個 12 秒的查詢掃描。查詢出來的資訊我們需要在廣播中進行監聽才可得知。
private final BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); mUnpaireList.add(device); mUnpaireAdapter.notifyDataSetChanged(); } } };//註冊廣播IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mBtReceiver, filter);//同時別忘了銷燬時登出廣播
第四步:配對連線
在這裡我們往往需要一臺裝置做伺服器端一臺做客戶端,實際上就是 app 開啟了一個伺服器執行緒讓藍芽的 socket 可以連線。連線完成後再使用 I/O Stream 進行資料互動。
1、伺服器執行緒
我們需要用 listenUsingInsecureRfcommWithServiceRecord(String,UUID) 獲取 BluetoothServerSocket。
Q2:
listenUsingRfcommWithServiceRecord()
和listenUsingInsecureRfcommWithServiceRecord()
有什麼區別?
A2:從名字來看似乎是安全不安全的區別,但是實際上我並沒有找到相關資料佐證。也有文章描述客戶端的 socket 建立createRfcommSocketToServiceRecord
是安卓2.3系統及以下用的,新的安卓要用createInsecureRfcommSocketToServiceRecord
,所以對應著伺服器端也用Insercure吧。
伺服器監聽中,由於 accept() 方法是阻塞的,所以需要子執行緒中處理。
private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; public AcceptThread() { BluetoothServerSocket tmp = null; try { tmp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = mmServerSocket.accept(); mmServerSocket.clost(); mInputStream = socket.getInputStrem(); mOutputStream = socket.getOutputStream(); byte[] buffer = new byte[1024]; int bytes; while (true) { try{ //讀取buffer資訊列印出來 bytes = mInputStream.read(buffer); String s = new String(buffer, 0, bytes); sendHandlerMsg(s); } carch(IOException e){ break; } } } }
2、客戶端連線
客戶端連線和服務端連線相似。當然首先你要獲取到要配對的裝置 BluetoothDevice,然後獲取 BluetoothSocket ,使用 mSocket.connect() 連線即可。他們的邏輯基本相同,在官方文件中也有相關的描述。
在這裡因為實際上我的需求是使用手機連線一個硬體裝置,所以我選擇封裝了一個藍芽工具類,把藍芽開啟連線等客戶端相關操作封裝到 BluetoothManager 中。其中 ConnectThread 和 ReadThread 抽成兩個Runnable 放線上程池中處理。當 socket 連線成功後獲取到 IO 流來進行讀寫操作。讀操作因為屬於阻塞操作放在子執行緒。程式碼這裡就不貼了,文末有此 demo 的地址。有興趣的也可以自己去實現一下。
第五步:其他
剩下的就是佈局和互動邏輯的實現,這裡就不在一一闡述了。
總結
藍芽的相關操作感覺和 Socket 非常地相似,都是進行端對端繫結,然後進行資料傳輸。所以同理也應該會存在類似 Socket 的各種問題,比如說丟包,斷開連線需要心跳檢測,重連機制等等。這個demo只是對API進行了一定程度的整合,還存有不少的問題。
作者:白帽子耗子
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4606/viewspace-2821607/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- iOS藍芽開發 Bluetooth藍芽CoreBluetooth 藍芽中心裝置的實現 藍芽外設的實現 有DemoiOS藍芽
- Android:藍芽實現一對一聊天Android藍芽
- iOS 藍芽4.0開發使用(內附Demo)iOS藍芽
- 藍芽藍芽
- Android藍芽使用詳解(普通藍芽)Android藍芽
- ESP32藍芽學習--藍芽概念學習藍芽
- java+藍芽Java藍芽
- 藍芽模組藍芽模組
- MASA MAUI Plugin IOS藍芽低功耗(三)藍芽掃描UIPluginiOS藍芽
- MASA MAUI Plugin 安卓藍芽低功耗(一)藍芽掃描UIPlugin安卓藍芽
- 白色藍芽耳機藍芽
- BLE低功耗藍芽藍芽
- iOS藍芽開發iOS藍芽
- 藍芽解鎖AutoLock 1.0.2 Mac中文版 (藍芽WiFi解鎖工具)藍芽MacWiFi
- 電腦藍芽怎麼連線 電腦連線藍芽的方法藍芽
- 藍芽共享網路怎麼用 win10藍芽共享網路藍芽Win10
- Android Ble藍芽入門Android藍芽
- Android開發--藍芽操作Android藍芽
- 藍芽Beacon格式詳解藍芽
- 藍芽韌體升級藍芽
- 怎麼更新電腦藍芽驅動 win10藍芽驅動更新藍芽Win10
- 手機藍芽硬體APP公司分析藍芽自動重連機制藍芽APP
- 藍芽耳機怎麼恢復中文模式 藍芽耳機調不了中文藍芽模式
- Mac藍芽連線有問題該如何?教你重置Mac藍芽模組Mac藍芽模組
- thinkphp5.0+workerman聊天室demoPHP
- 藍芽耳機怎麼按都不亮了 藍芽耳機長按無反應藍芽
- omthing TWS藍芽耳機怎麼樣?omthing TWS藍芽耳機全面評測藍芽
- 藍芽win10如何開啟_w10系統藍芽怎麼開藍芽Win10
- 藍芽耳機5.0和5.2哪個好 藍芽5.0和5.2的區別藍芽
- 2.4g和藍芽哪個好 2.4g和藍芽的區別藍芽
- 藍芽(Bluetooth)音訊協議藍芽音訊協議
- 富芮坤藍芽學習藍芽
- 藍芽解鎖Mac工具 - BLEUnlock藍芽Mac
- 藍芽音樂之歌詞同步藍芽
- iOS 藍芽開發 - swift版iOS藍芽Swift
- android藍芽BLE(三) —— 廣播Android藍芽
- 小程式之藍芽的使用藍芽
- android藍芽BLE(二) —— 通訊Android藍芽