導航:首頁 > 操作系統 > androidc藍牙

androidc藍牙

發布時間:2022-12-20 03:04:32

1. android 低功耗藍牙(Ble) 開發總結

Android 從 4.3(API Level 18) 開始支持低功耗藍牙,但是只支持作為中心設備(Central)模式,這就意味著 Android 設備只能主動掃描和鏈接其他外圍設備(Peripheral)。從 Android 5.0(API Level 21) 開始兩種模式都支持。

低功耗藍牙開發算是較偏技術,實際開發中坑是比較多的,網上有很多文章介紹使用和經驗總結,但是有些問題答案不好找,甚至有些誤導人,比如 :獲取已經連接的藍牙,有的是通過反射,一大堆判斷,然而並不是對所有手機有用,關於Ble傳輸速率問題的解決,都是默認Android每次只能發送20個位元組,然而也並不是,,,下面進入正文。

這里用的是 Android5.0 新增的掃描API,

這里說一下,如果做藍牙設備管理頁面,可能區分是否是已連接的設備,網上又通過反射或其他挺麻煩的操作,也不見得獲取到,官方Api 就有提供

與外圍設備交互經常每次發的數據大於 mtu的,需要做分包處理,接收數據也要判斷數據的完整性最後才返回原數據做處理,所以一般交互最少包含包長度,和包校驗碼和原數據。當然也可以加包頭,指令還有其他完整性校驗。下面分享幾個公用方法:

我自己封裝的一個BleUtil ,因為涉及跟公司業務關聯性太強(主要是傳輸包的協議不同)就先不開源出來了,如果這邊文章對大家有幫助反饋不錯,我會考慮上傳個demo到github供大家使用,
在這先給大家推薦一個不錯 Demo ,裡面除了沒有分包,協議,和傳輸速率。基本的功能都有,而且調試數據到列印到界面上了。最主要是它可以用兩個個手機一個當中心設備一個當外圍設備調試。

首先傳輸速率優化有兩個方向,1 外圍設備傳輸到Android 。2 Android傳輸到外圍設備。
我在開發中首先先使用上面那位仁兄的demo調試,兩個Android 設備調試不延時,上一個成功馬上下一個,最多一秒發11個20位元組的包。

後來和我們的藍牙設備調試時發現發送特別快,但是數據不完整,他藍牙模塊接收成功了,但是透傳數據到晶元處理時發現不完整,我們的硬體小夥伴說因為 波特率 限制(差不多每10位元組透傳要耗時1ms)和藍牙模塊的buff (列印時是最多100byte,100列印的)限制,就算藍牙模塊每包都告訴你接收成功,也是沒透傳完就又接收了。後來通過調試每次發20K數據,最後是 Android 發是 20位元組/130ms 穩定。給Android 發是 20位元組/ 8ms 。 (天殺的20位元組,網上都是說20位元組最多了)

後來看了國外一家物聯網公司總結的 Ble 吞吐量的文章(上面有連接),知道Android 每個延時是可以連續接收6個包的。就改為 120位元組/ 16ms (為啥是16ms,不是每次間隔要6個包嗎,怎麼像間隔兩次,這時因為波特率影響,多了5個包100位元組,差不多 我們的單片機透傳到藍牙模塊要多耗時不到10ms )
而Android 發數據可以申請 我們設備的mtu 來得到最多每次能發多少位元組。延時還是130ms,即:241位元組/ 130ms 提高12倍,這個速度還可以。

根據藍牙BLE協議, 物理層physical layer的傳輸速率是1Mbps,相當於每秒125K位元組。事實上,其只是基準傳輸速率,協議規定BLE不能連續不斷地傳輸數據包,否則就不能稱為低功耗藍牙了。連續傳輸自然會帶來高功耗。所以,藍牙的最高傳輸速率並不由物理層的工作頻率決定的。

在實際的操作過程中,如果主機連線不斷地發送數據包,要麼丟包嚴重要麼連接出現異常而斷開。

在BLE裡面,傳輸速度受其連接參數所影響。連接參數定義如下:

1)連接間隔。藍牙基帶是跳頻工作的,主機和從機會商定多長時間進行跳頻連接,連接上才能進行數據傳輸。這個連接和廣播狀態和連接狀態的連接不是一樣的意思。主機在從機廣播時進行連接是應用層的主動軟體行為。而跳頻過程中的連接是藍牙基帶協議的規定,完全由硬體控制,對應用層透明。明顯,如果這個連接間隔時間越短,那麼傳輸的速度就增大。連接上傳完數據後,藍牙基帶即進入休眠狀態,保證低功耗。其是1.25毫秒一個單位。

2)連接延遲。其是為了低功耗考慮,允許從機在跳頻過程中不理會主機的跳頻指令,繼續睡眠一段時間。而主機不能因為從機睡眠而認為其斷開連接了。其是1.25毫秒一個單位。明顯,這個數值越小,傳輸速度也高。

藍牙BLE協議規定連接參數最小是5,即7.25毫秒;而Android手機規定連接參數最小是8,即10毫秒。iOS規定是16,即20毫秒。

連接參數完全由主機決定,但從機可以發出更新參數申請,主機可以接受也可以拒絕。android手機一部接受,而ios比較嚴格,拒絕的概率比較高。

參考:
在iOS和Android上最大化BLE吞吐量
最大化BLE吞吐量第2部分:使用更大的ATT MTU

2. Android 藍牙開發(三)-藍牙的詳細介紹

前面的兩篇文章,主要是在 Android 官網關於藍牙介紹的基礎上加上自己的理解完成的。主要針對的是 Android 開發中的一些 API 的使用。
第一篇文章 Android 藍牙開發(一) 主要是介紹了普通的藍牙在 Android 開發中的運用。
第二篇文章 Android 藍牙開發(二) 主要是介紹了低功耗藍牙的開發。
這篇文章主要介紹的是藍牙的歷史和一些關於藍牙的通用知識,還有廣播包的知識。要想徹底了解藍牙開發,這些基礎的知識也是需要的,就像網路協議一樣,這些都是基礎的內容。我們的 API 的調用都是以這個為基礎的,了解這些,開發過程中遇到問題,才可以知道什麼怎麼一回事。

下篇文章主要講的就是實際開發中的一些坑。

藍牙其實就是一種近距離無線通信技術。

從下到上分別為:控制器(Controller)-->主機(host)-->應用(Application)

詳細介紹各個層的含義:

BLE 應用可以分為兩大類:基於非連接的和基於連接的

意思就是外設和周邊設備不發生連接,主要靠掃描到的廣播來獲取信息。發送廣播的一方叫做 broadcaster 監聽廣播的一方叫做 oberver 在 GAP 層有對應的角色定義。

網路拓撲圖:

這種方式就是廣播設備不斷的向外發送廣播(含有特定的信息),然後觀察者接受到廣播按照兩者之間約定好的協議進行解析拿到有用的信息。例如:iBeacon,通過這種設備我們可以實現室內定位。

其實這些設備的角色可以即使廣播者又是觀察者。接收到廣播後作出了處理,然後又發送廣播。這樣就形成了雙向的網路,類似於網際網路,這就是藍牙 Mesh 組網。

廣播數據包格式:

每個廣播數據包由 31 byte 組成。分為有效數據和無效數據兩部分。

例子:

這里是掃描的數據包(轉換成了 16 進制,兩個代表一個位元組),第一個位元組是 02 表示後面的兩個位元組是數據部分,然後第二個位元組是 01 表示了數據的類型。後面一個位元組就是真正的數據了。這個廣播數據單元就分析完了。下面就是另一個數據單元了。依次類推,關於數據類型的解釋,官網有。

這是數據類型對應的含義表。

網路拓撲圖:

一個中心設備可連接多個外設,但是一個外設只能連接一個中心(外設連接成功後就會停止對外廣播,別人就發現不了它了)。其中一個中心設備的連接外設的數量也是有限的。

鏈接: https://mp.weixin.qq.com/s?__biz=MzU5NzA2NjQzMg==&mid=2247484141&idx=1&sn=&scene=21#wechat_redirect

3. Android 藍牙開發(一)

普通藍牙設備官方文檔

Android 平台包含藍牙網路堆棧支持 ,憑藉此支持,設備能以無線方式與其他藍牙設備交換數據。應用框架提供了通過 Android Bluetooth API 訪問藍牙功能的途徑。使用 Bluetooth API Android 應用可以執行下面的操作:

傳統藍牙適用於電池使用強度較大的操作,例如 Android 設備之間的流傳輸和通信等。針對具有低功耗要求的藍牙設備,Android 4.3(API 18)中引入了面向低功耗藍牙的 API 支持。

使用 Android Bluetooth API 來完成使用藍牙進行通信的四項主要任務: 設置藍牙 、 查找局部區域內的配對設備或可用設備 、 連接設備 ,以及在 設備之間傳輸數據 。

關於藍牙的 API 在 android.bluetooth 包中,下面介紹一下和藍牙相關的主要類:

在 BluetoothProfile IPC 客戶端連接到服務(即,運行特定配置文件的內部服務)或斷開服務連接時向其發送通知的介面。

使用藍牙必須聲明許可權 BLUETOOTH 才可以執行藍牙通信。

1、獲取藍牙適配器

例如:我們可以查詢所有已配對的設備,然後使用 ArrayAdapter 向用戶顯示每台設備的名稱:

要發起連接僅需要知道目標藍牙設備的 Mac 地址就可以了。

注意 執行 discovery 對於藍牙適配器來說是一個非常繁重的過程,並且會消耗大量資源。在找到要連接的設備後, 要確保使用 cancelDiscovery() 來停止發現,然後嘗試連接 。如果您已經和某台設備進行連接,那麼這個時候執行發現操作會大幅度的減少此連接可用的帶寬!因此不應該在處於連接狀態的時候執行發現操作!

例如:

在連接之前如果兩個設備沒有配對,則系統會自動發出配對請求。

伺服器套接字接受連接的基本過程

放在子線程中去執行。

例子:

客戶端連接的基本過程

調用 connect() 的時候要確保客戶端沒有執行發現操作。如果執行了會大幅度降低連接的速度,增加失敗的可能。

例子

在連接之前調用 cancleDiscovery() 在進行連接之前應該始終調用這個方法,而且調用的時候無需檢測是否正在掃描。

過程:

從 Android 3.0 開始, Bluetooth API 便支持使用藍牙配置文件。藍牙配置文件是適用於設備間藍牙通信的無線介面規范。

1、藍牙配置文件就是設備間通信(藍牙設備)的一種規范

免提配置文件便是一個示例,對於連接到無線耳機的手機,兩台設備都必須支持免提配置文件。我們也可以通過實現介面 BluetoothProfile 來寫入自己的類來支持特定的藍牙配置文件。Android API 提供了以下的幾種藍牙配置文件的實現:

2、使用配置文件的基本步驟

創建 HDP 應用:

關於普通藍牙設備和普通藍牙設備之間的連接通信

關於藍牙設備和藍牙儀器(藍牙耳機、電子秤等等類似產品)
這種之間的通信是通過配置文件代理來實現的。
都有一個對應的配置文件代理類。具體的操作是通過這個對象來完成。

參考: https://mp.weixin.qq.com/s?__biz=MzU5NzA2NjQzMg==&mid=2247484128&idx=1&sn=&scene=21#wechat_redirect

4. android手機怎樣通過藍牙傳輸文件

手機通過藍牙傳輸文件的使用方法如下:
1.接收者:進入設定-藍牙-滑塊打開-將設備可見打鉤-在可見時間內讓對方發送文件-選擇是否接收-完成即可。
2.發送者:進入我的文件-長按需要傳輸的文件不鬆手-共享通過-藍牙-打開-掃描設備(接收方需開啟可見)-選擇接收者-完成即可。

5. syu android藍牙連接方法

syu android藍牙連接方法:打開其他設備的藍牙,並使其對其他設備可見。打開下拉頂簾,點擊藍牙圖標使其變為綠色,跳出提示框,勾選對其他設備可見。

syu android判斷藍牙模塊是否開啟,blueadapter.isEnabled() true表示已經開啟,false表示藍牙並沒啟用。

syu android啟動配置藍牙可見模式,即進入可配對模式Intent in=newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)。

藍牙連接技術優勢:

支持語音和數據傳輸;採用無線電技術,傳輸范圍大,可穿透不同物質以及在物質間擴散;採用跳頻展頻技術,抗干擾性強,不易竊聽;使用在各國都不受限制的頻譜,理論上說,不存在干擾問題;功耗低;成本低。藍牙的劣勢:傳輸速度慢。

藍牙的技術性能參數:有效傳輸距離為10cm~10m,增加發射功率可達到100米,甚至更遠。收發器工作頻率為2.45GHz ,覆蓋范圍是相隔1MHz的79個通道(從2.402GHz到2.480GHz )。




6. Android開發之藍牙(Bluetooth)

在上一篇中有介紹了Wifi與網路連接處理
Android開發之WiFi與網路連接處理
下面,來繼續說說Android中藍牙的基本使用。

Bluetooth是目前使用的最廣泛的無線通訊協議之一,主要針對短距離設備通訊(10米),常用於連接耳機、滑鼠和移動通訊設備等。

值得一提的是:
android4.2新增了部分新功能,但是對於Bluetooth熟悉的人或許開始頭疼了,那就是Android4.2引入了一個新的藍牙協議棧針BLE。谷歌和Broadcom之間的合作,開發新的藍牙協議棧,取代了基於堆棧的Bluez。因此市場上出現了老設備的兼容問題,很多藍牙設備在android4.2手機上不能正常使用。

BluetoothAdapter簡單點來說就是代表了本設備(手機、電腦等)的藍牙適配器對象。

first:we need permission
要操作藍牙,先要在AndroidManifest.xml里加入許可權

**下面來看看如何使用藍牙。 **↓↓↓****
Demo已就緒:

返回值:如果設備具備藍牙功能,返回BluetoothAdapter 實例;否則,返回null對象。

打開藍牙設備的方式:
1.直接調用函數enable()去打開藍牙設備 ;
2.系統API去打開藍牙設備,該方式會彈出一個對話框樣式的Activity供用戶選擇是否打開藍牙設備。

注意: 1.如果藍牙已經開啟,不會彈出該Activity界面。2.在目前大多數Android手機中,是不支持在飛行模式下開啟藍牙的。如果藍牙已經開啟,那麼藍牙的開關 ,狀態會隨著飛行模式的狀態而發生改變。

1. 搜索藍牙設備
使用BluetoothAdapter的startDiscovery()方法來搜索藍牙設備
startDiscovery()方法是一個非同步方法,調用後會立即返回。該方法會進行對其他藍牙設備的搜索,該過程會持續12秒。該方法調用後,搜索過程實際上是在一個System Service中進行的,所以可以調用cancelDiscovery()方法來停止搜索(該方法可以在未執行discovery請求時調用)。

系統開始搜索藍牙設備
^( *  ̄(oo) ̄ ) ^ 系統會發送以下三個廣播:

2.掃描設備

3.定義廣播接收器接收搜索結果

4.注冊廣播

獲取附近的藍牙設備

第一步建立連接:首先Android sdk(2.0以上版本)支持的藍牙連接是通過BluetoothSocket建立連接,服務端BluetoothServerSocket和客戶端(BluetoothSocket)需指定同樣的UUID,才能建立連接,因為建立連接的方法會阻塞線程,所以伺服器端和客戶端都應啟動新線程連接。

(這里的服務端和客戶端是相對來說的)
兩個藍牙設備之間的連接,則必須實現服務端與客戶端的機制。
當兩個設備在同一個RFCOMM channel下分別擁有一個連接的BluetoothSocket,這兩個設備才可以說是建立了連接。

服務端設備與客戶端設備獲取BluetoothSocket的途徑是不同的。
1,服務端設備是通過accepted一個incoming connection來獲取的,
2,客戶端設備則是通過打開一個到服務端的RFCOMM channel來獲取的。

服務端
通過調用BluetoothAdapter的(String, UUID)方法來獲取BluetoothServerSocket(UUID用於客戶端與服務端之間的配對)

客戶端
調用BluetoothService的(UUID)方法獲取BluetoothSocket(該UUID應該同於服務端的UUID)。
調用BluetoothSocket的connect()方法(該方法為block方法),如果UUID同服務端的UUID匹配,並且連接被服務端accept,則connect()方法返回。

數據傳遞,通過以上操作,就已經建立的BluetoothSocket連接了,數據傳遞無非是通過流的形式
獲取流

該類就是關於遠程藍牙設備的一個描述。通過它可以和本地藍牙設備---BluetoothAdapter連接通信。

好多東西我也不知道怎麼描述,下面給出Demo:
剛好有剛學習的小夥伴問我ListView怎麼用,那我就用ListView。

源碼
RairDemo
GitHub: https://github.com/Rairmmd/android-demo
Coding: https://coding.net/u/Rair/p/RairDemo/git

7. android 獲取藍牙Mac地址

android 從6.0開始,通過BluetoothAdapter.getDefaultAdapter().getAddress()獲取的地址是一個固定值02:00:00:00:00:00。6.0已經對藍牙Wi-Fi的MAC地址做了隱藏。

以下方法能正確的獲取android自帶藍牙的Mac地址:

1.添加net.vidageek:mirror:1.6.1

2.實現過程

本人也嘗試過其他方法獲取,比如從cat /sys/class/net/wlan0/address 或者/sys/class/net/eth0/address路徑獲取,該方式有些手機能獲取得到,有的不能或缺,獲取到的Mac 地址還不一定準確。

8. Android-藍牙傳輸

通過藍牙傳輸數據與Socket類似。在網路中使用Socket和ServerSocket控制客戶端和服務端的數據讀寫。而藍牙通訊也由客戶端和服務端Socket來完成。藍牙客戶端Socket是BluetoothSocket,藍牙服務端Socket是BluetoothServerSocket。這兩個類都在android.bluetooth包中。

如果打算建議兩個藍牙設備之間的連接,則必須實現伺服器端與客戶端的機制。當兩個設備在同一個RFCOMM channel下分別擁有一個連接的BluetoothSocket,這兩個設備才可以說是建立了連接。

伺服器設備與客戶端設備獲取BluetoothSocket的途徑是不同的。伺服器設備是通過accepted一個incoming connection來獲取的,而客戶端設備則是通過打開一個到伺服器的RFCOMMchannel來獲取的。

通過調用BluetoothAdapter的(String, UUID) 方法來獲取
BluetoothServerSocket(UUID用於客戶端與伺服器端之間的配對)調用BluetoothServerSocket的 accept() 方法監聽連接請求,如果收到請求,則返回一個BluetoothSocket實例。

如果不想在accept其他的連接,則調用BluetoothServerSocket的 close() 方法釋放資源(調用該方法後,之前獲得的BluetoothSocket實例並沒有close。但由於RFCOMM一個時刻只允許在一條channel中有一個連接,則一般在accept一個連接後,便close掉BluetoothServerSocket)

通過搜索得到伺服器端的BluetoothService,調用BluetoothService的(String, UUID)方法獲取BluetoothSocket(該UUID應該同於伺服器端的UUID)。

調用BluetoothSocket的 connect() 方法(該方法為block方法),如果UUID同伺服器端的UUID匹配,並且連接被伺服器端accept,則 connect() 方法返回。

9. Android藍牙協議-藍牙配對與連接

藍牙設備在連接前,會先檢查設備是否已經配對過,如果沒有則先配對,配對完成後,再開始連接。

藍牙連接開始於設備列表 DeviceListPreferenceFragment的onPreferenceTreeClick方法。
DeviceListPreferenceFragment是藍牙設備列表,點擊其中一個藍牙設備,開始藍牙的連接過程。

調用onDevicePreferenceClick方法,接著調用BluetoothDevicePreference的onClicked方法,開始連接,以及連接前的狀態檢測。

獲取mCachedDevice的綁定狀態,

pair方法會調用CachedBluetoothDevice.startPairing,啟動配對

createBond調用BluetoothDevice.createBond方法,BluetoothDevice.createBond接著調用IBluetooth.createBond方法,下面會調用藍牙遠程服務。
和藍牙掃描一樣,實現IBluetooth介面的類是AdapterServiceBinder,

AdapterServiceBinder實現IBluetooth.Stub介面,並且是AdapterService的私有內部類, AdapterServiceBinder接受事件,都會轉交AdapterService處理 ,所以IBluetooth.createBond方法會調用AdapterService.createBond方法。

createBond方法會檢查一下遠程設備屬性信息,再次取消藍牙掃描任務,將配對任務轉交mBondStateMachine,由狀態機處理該信息。
BondStateMachine狀態機的初始狀態是StableState,所以BondStateMachine.CREATE_BOND由StableState處理,StableState在processMessage中調用BondStateMachine.createBond方法

createBondNative方法實現com_android_bluetooth_btservice_AdapterService.cpp中

閱讀全文

與androidc藍牙相關的資料

熱點內容
能否給隱藏相冊加密 瀏覽:596
糖心app改什麼名 瀏覽:823
戰地1控伺服器如何部署 瀏覽:394
xp還原系統輸入命令 瀏覽:323
mysql命令行版本 瀏覽:303
如何進入itunes找文件夾 瀏覽:832
CAD中重復命令使用 瀏覽:477
心智pdf 瀏覽:475
網站電台直播間源碼 瀏覽:852
文件夾14c和18c的區別 瀏覽:34
android隱式調用 瀏覽:667
plc的編程指令邊沿繼電器 瀏覽:723
voc文件夾 瀏覽:865
租廣東聯通伺服器注意什麼雲空間 瀏覽:934
javascript高級程序設計pdf 瀏覽:292
pwm單片機原理 瀏覽:348
ai演算法在線修復圖片 瀏覽:982
scratch編程中如何做射擊游戲 瀏覽:479
at89c51編程器 瀏覽:344
項目經理叫醒程序員 瀏覽:344