整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          低功耗藍牙(BLE)和傳感器的使用

          、低功耗藍牙的使用

          Android中關于藍牙的開發文檔,可以參考Google提供的官方藍牙文檔:https://developer.android.google.cn/guide/topics/connectivity/bluetooth.html

          在Android開發中,應用可通過官方提供的藍牙API執行以下操作:

          • 掃描其他藍牙設備
          • 查詢本地藍牙適配器的配對藍牙設備
          • 建立 RFCOMM 通道
          • 通過服務發現連接到其他設備
          • 與其他設備進行雙向數據傳輸
          • 管理多個連接

          藍牙

          一個近距離無線通信技術,最早是由愛立信研發出來。藍牙 Bluetooth 這個詞是一個丹麥的國王的綽號,當時研發它的工程師正在看一個關于這個國王的書,就起了這個名字。藍牙的技術特點是:

          • 近距離通信:典型距離是 10 米以內;
          • 傳輸效率:傳輸速度最高可達 24 Mbps
          • 多連接:藍牙技術支持多設備連接、安全性高

          藍牙從被發明到目前,經過了幾個版本的變化:

          • 1.0版本:99年發布
          • 2.1版本:使用范圍最廣泛,經典藍牙
          • 3.0版本:高速藍牙,最高傳輸速度達到24Mbps
          • 4.0/4.1版本:新增低功耗藍牙
          • 5.0版本:物聯網

          低功耗藍牙

          低功耗藍牙全稱為Bluetooth Low Energy,簡稱為BLE,最大特點就是低功耗,另外低功耗藍牙還具備成本低,連接速度快,安全性高的特點。當然,低功耗藍牙也相應的會有一些不足,比如說:低功耗對應的是低傳輸效率,因此低功耗藍牙主要用來傳輸少量數據,結合低功耗的特點,非常適合用在移動智能設備上。

          低功耗藍牙分為兩種模式:單模和雙模。

          • 單模:只能執行低功耗協議棧,即只支持BLE。
          • 雙模:既支持傳統藍牙又支持BLE藍牙。

          注意:需要在Android 4.3及以上版本才能支持具備低功耗功能的藍牙4.0。

          BLE協議棧

          首先來看一下使用藍牙的基本流程:

          先簡單來了解一下低功耗藍牙的協議框架,在BLE協議棧中,大致分為三個部分,從下到上依次為:控制器(Controller) 、主機(Host)、應用(Applications)。

          • 控制器:協議棧的最底層,直接與硬件相關,由廠商直接實現。
          • 主機:硬件層的抽象層,與具體的硬件和常見無關,可以理解為接口。
          • 應用層:使用Host層提供的API,進而開發的應用。

          協議層從下往上,依次包含如下協議:

          • Attribute Protocol:簡稱為 ATT,屬性協議,Host層的一個協議,是BLE通信的基礎。ATT 把數據封裝,向外暴露為“屬性”,提供“屬性”的為服務端,獲取“屬性”的為客戶端。ATT 是專門為低功耗藍牙設計的,結構非常簡單,數據長度很短。每個屬性都有一個唯一的UUID,屬性以characteristics and services的形式傳輸。
          • Generic Attribute Profile:簡稱為GATT,通用屬性配置文件,建立在前面說的 ATT 的基礎上,對 ATT 進行進一步的邏輯封裝,定義數據的交互方式和含義。GATT 按照層級定義了三個概念:
            • Service:服務,一個 Service 包含若干個 Characteristic。
            • Characteristic:特征,一個 Characteristic 可以包含若干 Descriptor。
            • Descriptor:描述,數據的讀寫操作。
          • Generic Access Profile:簡稱為GAP,通用訪問控制配置文件,用來控制設備連接和廣播,GAP使你的設備被其他設備可見,并決定了你的設備是否可以或者怎樣與合同設備進行交互。

          Android BLE API

          • Android SDK 中 BLE 相關的 API 都在 android.bluetooth.* 中。
          • 5.0版本中:android.bluetooth.le*

          權限

          • 要在 APP 中使用藍牙功能,需要在 Manifest 中申請藍牙相關的權限。
          • Android 6.0及以上版本:藍牙 + 定位權限。為什么會有定位權限?BLE有定位的功能和能力。

          BLE核心API

          • BluetoothManager:藍牙管理服務。在Android基本框架中可以發現藍牙屬于最底層的驅動模塊中,可以公國context.getSystemService(Context.BLUETOOTH_SERVICE) 來進行獲取。
          • BluetoothAdapter:本地設備藍牙適配器。BluetoothAdapter可以完成:啟動設備發現,查詢已綁定(配對)設備的列表,使用已知MAC地址實例化 BluetoothDevice,并創建一個 BluetoothServerSocket 以監聽來自其他設備的連接請求,并啟動掃描藍牙LE設備等操作,該類屬于核心中的核心。
          • BluetoothAdapter.LeScanCallback:BLE掃描結果回調接口,在 Android 5.0以上 使用抽象類 ScanCallback。
          • BluetoothLeScanner:藍牙LE設備執行掃描相關操作類,使用該API要求Android 5.0(API21)以上。
          • BluetoothDevice:遠程藍牙設備,BluetoothDevice允許創建與相應設備的連接或關于它的查詢信息,例如名稱,地址,類和綁定狀態等。
          • BluetoothProfile:配置文件代理。每個公共配置文件實現這個接口。它有幾個直接子類,每個子類再不同場景中使用,如 BluetoothA2dp, BluetoothGatt, BluetoothGattServer, BluetoothHeadset, BluetoothHealth。在當前例子中使用到的是 BluetoothGatt。
          • BluetoothGatt:提供藍牙GATT功能,以實現與藍牙智能或智能就緒設備的通信。使用該類做連接、斷開、關閉等操作。
          • BluetoothGattCallback:設備連接時的回調接口。

          UUID

          UUID 是全局唯一標識,是128bit的值,為了便于識別和閱讀,一般標示成:8-4-4-12 的16進制格式。

          Android 中提供了 UUID.randomUUID() 來生成一個隨機的 UUID。

          在低功耗藍牙中,長度為128bit的UUID數據長度是受限的,因此藍牙中又產生出來了16bit和32bit的UUID,本質上和128bit的UUID一樣。

          Android 中BLE的操作步驟

          • ① 獲取到BluetoothAdapter:代表設備自己的藍牙適配器,整個系統只有一個藍牙適配器,應用程序可以使用此對象與其交互。獲取方法是通過 BluetoothManager 獲取。
          • ② 啟用藍牙設備:isEnable() 查看是否啟用,通過 BluetoothAdapter.ACTION_REQUEST_ENABLE 來啟動
          • ③ 查找BLE設備:通過startLeScan(callBack); 方法來開啟掃描;另外還可以使用BluetoothLeScanner來掃描。

          與Android BLE設備通信

          開發BLE應用,主要有兩大類:

          • 基于非連接的通信應用:使用的是BLE的廣播機制,又稱作是Beacon。共有兩個角色:發送方負責發送廣播,稱之為Boradcaster,另外一方為監聽方,監聽廣播信號,稱之為Observer。
          • 基于連接的通信應用:基于連接的通信是通過建立GATT連接,讓后進行數據的收發。也有兩個角色:連接發起方,稱之為中心設備(Central),另外一方是被連接的設備,稱之為外設Peripheral。

          本篇文章中,我們來討論面向連接的通信的情況。如果要與另外一個BLE設備進行通信,需要經過連接,確認狀態,然后再通信的過程。首先是開啟連接,然后會觸發對應的連接回調,然后發現服務,觸發發現服務回調,獲取服務內部的特征值,對其讀寫命令(和 BLE 共同約束的規范),就是這么一個過程,比較簡單。

          • 連接到GATT服務器:如果要與BLE進行通信,第一步就是要連接到該設備的 GATT 服務。使用connectGatt方法鏈接,有三個參數,最后一個參數為連接的回調函數,表是處理鏈接的狀態,所有交互均從回調中進行處理。
          • 讀 BLE 屬性:一旦Android設備連接到GATT的服務器并且發現了BLE服務,則可以讀取或者寫入相關的屬性,執行相關的操作了。
          • 釋放GATT:當操作完成后,要記得關閉設備bluetoothGatt.close()。

          二、WIFI的使用

          每個移動智能設備幾乎都帶有WIFI連接功能,在Android系統中,同樣也提供了WIFI開發的相關的API。

          WIFI API

          Android系統提供的WIFI API,主要包含在兩個包中:

          • android.net.wifi包
          • android.net.wifi.p2p包

          和wifi相關的核心API主要有以下幾個內容:

          • WifiManager:提供管理WiFI連接的大部分API
          • ScanResult:已經檢測出的接入點(包括接入點的地址、名稱、身份認證、頻率、信號強度)
          • WifiConfiguration:WiFi連接的網絡配置(包括安全配置等)
          • WifiInfo:WiFi無線連接的描述,主要包括接入點、網絡連接狀態、隱藏的接入點、IP地址、連接速度、MAC地址、網絡ID、信號強度等等信息。
          • WifiManager.WifiLock:通常情況下當用戶在一段時間內沒有任何操作的時候,WiFi網絡會自動關閉。我們使用WifiLock來鎖定WiFi網絡,使其一直保持連接,直到這個鎖被釋放。多個應用程序可能有多個鎖,當多有的應用程序的鎖都被釋放的時候,WiFi才被關閉。

          WIFI 使用說明

          • WifiManager:context.getSystemService(Context.WIFI_SERVICE);
          • 打開WiFi:mWifiManager.setWifiEnabled(true); 關閉wifi為false
          • 創建一個WifiLock:mWifiManager.createWifiLock("lock_name");
          • 鎖定WifiLock:mWifiLock.acquire();
          • 釋放WifiLock:mWifiLock.release();
          • WiFi連接:
          public void addNetworkAndConn(WifiConfiguration wcg) {
              int netId = mWifiManager.addNetwork(wcg);
              mWifiManager.enableNetwork(netId, true);
          }
          • 斷開一個指定ID的WiFi:
          public void disconnectWifi(int netId) {
              mWifiManager.disableNetwork(netId);
              mWifiManager.disconnect();
          }
          • 掃描可接入的WiFi:
          public void startScan() {
              mWifiManager.startScan();
              // 得到掃描結果
              List<ScanResult> wifiList = mWifiManager.getScanResults();
              // 得到配置好的網絡連接
              List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
          }

          WIFI 權限

          在進行wifi開發時,既要用到網絡,也要用到硬件資源,因此需要申請一些必要的權限,而且涉及到的還比較的多,主要的權限如下:

          <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> 
          <uses-permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"></uses-permission> 
          <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission> 
          <uses-permission android:name="android.permission.INTERNET"></uses-permission> 
          <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> 
          <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"></uses-permission>

          WIFI直連

          WIFI Direct 意為通過 WIFI 直接建立連接。允許無線網絡中的設備無須通過無線路由器即可相互連接。這種標準支持 WIFI 的無線設備像藍牙那樣以點對點的形式互連,但是在傳輸速度與傳輸距離方面都比藍牙有大幅提升。

          WIFI Direct 提供 WifiP2pManager 類,其功能主要分為以下三部分:

          • WifiP2pManager 類提供相關 API 用于發現可連接的點,并進行請求和建立連接。
          • 每個 WifiP2pManager 的方法都要求傳入對應的監聽器,用于監聽對該方法是否成功運行。
          • 當檢測到特定事件,如可連接的點減少或者發現了新的可連接的點,WIFI Direct 框架會通過 Intent 通知用戶。

          WifiP2pManager的核心API用法說明如下所示:

          • initialize:為應用程序注冊 WIFI 框架。該方法必須在任何其他 WIFI Direct 方法被調用前調用,常放在Application中調用。
          • connect:與具有指定配置的 WIFI 設備建立點對點連接
          • cancelConnect:斷開連接
          • requestConnectInfo:獲取設備的連接信息
          • createGroup:以當前設備為擁有者創建一個點對點組
          • removeGroup:刪除當前的點對點組
          • requestGroupInfo:獲取點對點組的信息
          • discoverPeers:初始化發現對等點設備服務
          • requestPeers:獲取當前已發現的對等點設備列表

          在WifiP2pManager使用時,同樣支持使用各種監聽回調接口:

          • ActionListener:Wifi連接過程中的某個動作監聽。主要包括:connect、cancelConnect、createGroup、removeGroup、discoverPeers等回調函數
          • ChannelListener:initialize初始化的回調
          • ConnectionInfoListener:請求連接的回調,回傳連接信息
          • GroupInfoListener:點對點組的監聽信息
          • PeerListListener:點對點設備的監聽回調接口

          三、傳感器

          Android 傳感器屬于虛擬設備,可提供來自以下各種物理傳感器的數據:

          • 加速度計
          • 陀螺儀
          • 磁力計、
          • 氣壓計
          • 濕度傳感器
          • 壓力傳感器
          • 光傳感器
          • 近程傳感器
          • 心率傳感器

          以上的這些均可以歸納為傳感器類別,在Android中,這些傳感器有一個相同的定義文件,存在一個 sensors.h文件,其中定義了Android系統支持的每一種傳感器。格式為:ENSOR_TYPE_傳感器名稱。


          該圖為Android系統中傳感器的的架構和分層。可以看出,幾乎和Android系統整體的架構一樣。從上層到下層,從應用層到底層內核層。

          傳奇器核心API

          Android傳感器框架放在android.hardware包中,核心的API如下所示:

          • SensorManager:用于創建傳感器服務實例。該類提供了訪問和羅列傳感器的各種方法,用于注冊和注銷傳感器事件監聽器并獲取方向信息。該類也提供了幾個常量,用于報告傳感器的精度、數據獲取率和校正傳感器。
          • Sensor:用作創建某個特定傳感器的實例。該類提供了用于確定傳感器能力的各種方法。
          • SensorEvent:創建傳感器事件對象。傳感器事件對象包含傳感器事件的相關信息,包括原始的傳感器數據、傳感器類型、產生的事件、事件精度以及事件發生的時間戳等。
          • SensorEventListener:是一個接口,包含兩個回調方法。當傳感器的值發生改變或者傳感器的精度發生改變時,相關方法就會自動被調用。

          傳感器核心操作

          無論如何變化,其實通過上面的描述和介紹,我們看到,傳感器是底層系統提供的,數據也是相關的API返回獲取的。因此,在涉及到傳感器開發時,開發者的核心操作只有兩個:

          • 分析需求,明確使用哪個一個類別的傳感器,明確要獲取的傳感器數據。
          • 調用系統的API方法,監聽傳感器的的回調時間,獲取數據。

          因此,Android中的傳感器部分的應用開發,重點不是在于傳感器的使用,是開發者自己特定的應用,在獲取到數據后,對數據的處理和挖掘,是重中之重。

          Android傳感器分類

          Android中支持的傳感器分為很多類別,主要有:

          • TYPE_ACCELEROMETER:運動探測傳感器,硬件傳感器
          • TYPE_AMBIENT_TEMPERATURE:環境溫度傳感器,硬件傳感器
          • TYPE_GRAVITY:運動探測,軟件或者硬件傳感器
          • TYPE_GYROSCOPE:旋轉,硬件傳感器
          • TYPE_LIGHT:屏幕亮度傳感器,屬于硬件傳感器
          • TYPE_LINEAR_ACCELERATION:加速度傳感器,軟件或者硬件都有
          • TYPE_ORIENTATION:方向傳感器,屬于軟件傳感器
          • TYPE_PRESSURE:空氣壓力傳感器,屬于硬件傳感器
          • TYPE_PROXIMITY:距離傳感器,用于監測打電話時手機與耳朵的距離,屬于硬件傳感器

          四、SystemService

          經過本篇文檔的介紹,結合之前的課程內容,我們可以總結出一個規律。在Android開發時,很多情況下我們都可以直接通過某個上下文,獲取xxxManager,往往是某個管理者。這些管理者是Android系統提供的系統服務,我們可以統稱為SystemService,現在我們了解一下SystemService有關的內容,并做個總結。

          SystemService

          SystemService是系統提供給開發者的調用系統層的控制接口,應用層的開發者只需要了解這些接口的使用方式,就可以非常方便的進行系統控制,完成自己想要的功能操作,獲取系統的相關信息,而不需要了解接口的具體內部實現方式。這些SystemManager是在framework層或者更底層進行實現的。

          相反的對于Framework層的開發者而言,需要了解XXXManager服務的實現細節和方式,并維護Manager接口,擴展或者實現新接口等。

          我們可以列舉一下我們在學習過程中遇到的Manager,比如:

          • WindowManager:窗口操作的窗口管理服務
          • NotifacationManager:通知管理
          • AudioManager:Android系統的音頻管理者
          • LocationManager:GPS定位服務管理
          • StatusBarManager:狀態欄的管理者

          除此以外,還有很多很多,以上這些管理者,其實背后都是有一個系統服務SystemService。

          getSystemService

          getSystemService是Android很重要的一個API,它是Activity的一個方法,根據傳入的NAME來取得對應的Object,然后轉換成相應的服務對象。

          款指紋模塊

          支持APP遠程控制


          HLK-EL605A是一款藍牙半導體指紋鎖解決方案,與市面上已有的產品相比,該模組具有功耗低、識別速度快、識別準確度高等優勢。


          HLK-EL605A使用方便,尤其適合室內房門鎖等體積較小、使用電池供電的設備中,低功耗的同時可以保持優異的反應性能及高速的識別速度。


          HLK-EL605A模塊使用05mm*8Pin FPC插座與擴展板連接可以使用普通線纜進行連接,增強連接可靠性。


          HLK-EL605A的資料鏈接:

          https://h.hlktech.com/Mobile/download/fdetail/237.html


          一、指紋+APP兩種解鎖方式


          HLK-EL605A指紋模塊支持BLE5.1藍牙通訊,在日常使用中支持指紋識別解鎖和APP遠程控制解鎖兩種解鎖方式。


          01

          指紋極速解鎖




          HLK-EL605A指紋模塊采用電容式指紋傳感器,通過測量指紋信號,可以有效檢測假手指問題。指紋傳感器表面使用高硬度涂層,在日常使用中,可以極大的減少對指紋傳感器的磨損。


          0.3S內極速解鎖,指紋就是鑰匙,開門快人一步,非常適用于智能門鎖、考勤門鎖等產品。


          算法規格:

          ① 認假率FAR(FalseAcceptanceRate):<1/100000

          ② 拒真率 FRR(False Rejection Rate): <1%

          ③ 響應速度(平均):特征提取時間<0.25s,單枚平均匹配時間<0.002s

          ④ 指紋存儲:支持存儲20枚指紋特征

          ⑤ 支持指紋拼接,拼接最大次數:6次

          ⑥ 支持360°識別

          ⑦ 支持自學習功能


          02

          APP遠程控制

          HLK-EL605A指紋模塊支持通過涂鴉APP遠程控制。在通過藍牙添加指紋設備后,可以實現APP對指紋模塊的智能管理。


          涂鴉APP智能控制指紋模塊功能:

          ① 剩余電量實時顯示

          ② 查看開鎖記錄和警告信息

          ③ 快速添加或者刪除指紋

          ④ 遠程開鎖


          除了上述功能外,用戶可根據需求開發更多功能,提高產品的實用性。


          二、BLE5.1藍牙通訊

          HLK-EL605A指紋模塊支持存儲20枚指紋特征; 支持指紋拼接,拼接最大次數6次。

          同時,HLK-EL605A指紋模塊支持BLE5.1藍牙通訊,可以通過藍牙連接小程序和APP控制模塊,支持定制開發小程序和APP。



          三、支持電機、蜂鳴器等控制

          HLK-EL605A指紋模塊支持 3.4V~6V供電;支持1路電機芯片正反轉控制支持1路電機堵轉檢測;支持1路蜂鳴器控制;支持1路按鍵檢測;支持1路可擴展輸入/輸出IO。



          四、自學習功能

          當手指小面積接觸到采集器時,系統自動激活并采集對比指紋圖像及特征點信息。

          指紋識別過程中,新提取的指紋特征值識別成功后將該特征值融合到指紋數據庫中。要次用戶成功解鎖手機后,指紋傳感器就會記錄之前尚未錄入的指紋部分,然后將該區域添加到數據中,使指紋數據更完整。隨著時間的推移,數據庫中關于指紋的信息會更多,解鎖會更快。

          ndroid ble藍牙開發

          BLE介紹

          安卓4.3(API 18)為BLE的核心功能提供平臺支持和API,App可以利用它來發現設備、查詢服務和讀寫特性。相比傳統的藍牙,BLE更顯著的特點是低功耗。這一優點使AndroidApp可以與具有低功耗要求的BLE設備通信,如近距離傳感器、心臟速率監視器、健身設備等。

          BLE開發

          BLE權限添加

          為了在app中使用藍牙功能,必須聲明藍牙權限BLUETOOTH。利用這個權限去執行藍牙通信,例如請求連接、接受連接、和傳輸數據。如果想讓你的app啟動設備發現或操縱藍牙設置,必須聲明BLUETOOTH_ADMIN權限。注意:如果你使用BLUETOOTH_ADMIN權限,你也必須聲明BLUETOOTH權限。在你的app manifest文件中聲明藍牙權限。

          設置BLE

          你的app能與BLE通信之前,你需要確認設備是否支持BLE,如果支持,確認已經啟用。雖然現在的手機基本都支持BLE,但是考慮到程序的健碩性,如果設置為false,這個檢查是必需的。

          BluetoothAdapter類介紹

          獲取:所有的藍牙活動都需要藍牙適配器。BluetoothAdapter代表設備本身的藍牙適配器(藍牙無線)。整個系統只有一個藍牙適配器,而且你的app使用它與系統交互。下面的代碼片段顯示了如何得到適配器。注意該方法使用getSystemService()]返回BluetoothManager,然后將其用于獲取適配器的一個實例。Android 4.3(API 18)引入BluetoothManager。

          // 初始化藍牙適配器

          final BluetoothManager bluetoothManager =
          (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
          mBluetoothAdapter = bluetoothManager.getAdapter();

          有了mBluetoothAdapter之后就可以判斷當前藍牙開關狀態、藍牙未開啟情況下代碼里面自動開啟藍牙、以及掃描周邊的ble設備

          開啟藍牙

          接下來,你需要確認藍牙是否開啟。調用isEnabled())去檢測藍牙當前是否開啟。如果該方法返回false,藍牙被禁用。下面的代碼檢查藍牙是否開啟,如果沒有開啟,可以提示用戶去設置開啟藍牙。

          // 確保藍牙在設備上可以開啟
          if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
          //藍牙未開啟
          }

          發現BLE設備

          為了發現BLE設備,使用startLeScan())方法。這個方法需要一個參數BluetoothAdapter.LeScanCallback。你必須實現它的回調函數,那就是返回的掃描結果。因為掃描非常消耗電量,你應當遵守以下準則:

          1·只要找到所需的設備,停止掃描。

          2·不要在循環里掃描,并且對掃描設置時間限制。以前可用的設備可能已經移出范圍,繼續掃描消耗電池電量。

          以下代碼顯示如何掃描設備和停止掃描設備

          // 10秒后停止尋找.
          private static final long SCAN_PERIOD = 10000;
          private void scanLeDevice(final boolean enable) {
          if (enable) {
          // 經過預定掃描期后停止掃描
          mHandler.postDelayed(new Runnable() {
          @Override
          public void run() {
          mScanning = false;
          mBluetoothAdapter.stopLeScan(mLeScanCallback);
          }
          }, SCAN_PERIOD);
          mScanning = true;
          mBluetoothAdapter.startLeScan(mLeScanCallback);
          } else {
          mScanning = false;
          mBluetoothAdapter.stopLeScan(mLeScanCallback);
          }
          ...
          }
          ...
          }
          如果你只想掃描指定類型的外圍設備,可以改為調用startLeScan(UUID[], BluetoothAdapter.LeScanCallback)),需要提供你的app支持的GATT services的UUID對象數組。

          掃描的信息在LeScallCallback里面返回

          private BluetoothAdapter.LeScanCallback mLeScanCallback =
          new BluetoothAdapter.LeScanCallback() {
          //device 里面包含設備的mac地址和設備的名稱
          //scanRecord里面就是ble設備發出的廣播包數據
          //rssi表示ble設備的信號值,該值為負數,值越大表示信號值越好
          @Override
          public void onLeScan(final BluetoothDevice device, int rssi,
          byte[] scanRecord) {
          runOnUiThread(new Runnable() {
          @Override
          public void run() {
          mLeDeviceListAdapter.addDevice(device);
          mLeDeviceListAdapter.notifyDataSetChanged();
          }
          });
          }
          };

          連接到GATT服務端

          與一個BLE設備交互的第一步就是連接它——更具體的,連接到BLE設備上的GATT服務端。為了連接到BLE設備上的GATT服務端,需要使用connectGatt( )方法。這個方法需要三個參數:一個Context對象,自動連接(boolean值,表示只要BLE設備可用是否自動連接到它),和BluetoothGattCallback調用。

          mBluetoothGatt = device.connectGatt(this, false, mGattCallback);

          連接到GATT服務端時,由BLE設備做主機,并返回一個BluetoothGatt實例,然后你可以使用這個實例來進行GATT客戶端操作。請求方(Android app)是GATT客戶端。BluetoothGattCallback用于傳遞結果給用戶,例如連接狀態,以及任何進一步GATT客戶端操作。

          private final BluetoothGattCallback mGattCallback =
          new BluetoothGattCallback() {
          @Override
          public void onConnectionStateChange(BluetoothGatt gatt, int status,
          int newState) {//當連接狀態發生改變
          String intentAction;
          if (newState == BluetoothProfile.STATE_CONNECTED) {//當藍牙設備已經連接
          //獲取ble設備上面的服務
          Log.i(TAG, "Attempting to start service discovery:" +
          mBluetoothGatt.discoverServices());
          } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {//當設備無法連接
          }
          }
          @Override
          //調用discoverServices后的回調
          public void onServicesDiscovered(BluetoothGatt gatt, int status) {
          if (status == BluetoothGatt.GATT_SUCCESS) {
          //獲取服務成功
          } else {
          Log.w(TAG, "onServicesDiscovered received: " + status);
          }
          }
          @Override
          // 讀寫特性
          public void onCharacteristicRead(BluetoothGatt gatt,
          BluetoothGattCharacteristic characteristic,
          int status) {
          if (status == BluetoothGatt.GATT_SUCCESS) {
          }
          }
          ...
          };
          ...
          }

          發送數據

          首先通過UUID拿到對應的服務,再通過UUID拿到服務的特征,設置特征的屬性是BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE。設置成功后可以在該特征值上發送數據到ble設備和接收ble設備的數據。看到這里也許各位不熟ble開發和剛ble開發的看官也許就一臉懵逼,我只是想發送數據到ble設備,怎么一下子搞出個UUID 服務和特征值了,難道就不能和B/S開發一樣,連接之后我把數據發送到一個接口,服務器端就返回我需要的數據那么簡單。這還得從ble藍牙的架構說起。

          BLE分為三部分Service、Characteristic、Descriptor,這三部分都由UUID作為唯一標示符。一個藍牙4.0的終端可以包含多個Service,一個Service可以包含多個Characteristic,一個Characteristic包含一個Value和多個Descriptor,一個Descriptor包含一個Value。service是characteristic的集合.一個characteristic包括一個單一變量和0-n個用來描述characteristic變量的descriptor.Descriptor用來描述characteristic變量的屬性。例如,一個descriptor可以規定一個可讀的描述,或者一個characteristic變量可接受的范圍,或者一個characteristic變量特定的測量單位。一般來說,Characteristic是手機與BLE終端交換數據的關鍵.。

          舉個栗子:當我們想要用手機與BLE設備進行通信時,實際上也就相當于我們要去找一個學生交流,首先我們需要搭建一個管道,也就是我們需要先獲取得到一個BluetoothGatt,其次我們需要知道這個學生在哪一個班級,學號是什么,這也就是我們所說的serviceUUID,和charUUID。這里我們還需要注意一下,找到這個學生后并不是直接和他交流,他就好像一個中介一樣,在手機和BLE終端設備之間幫助這兩者傳遞著信息,我們手機所發數據要先經過他,在由他傳遞到BLE設備上,而BLE設備上的返回信息,也是先傳遞到他那邊,然后手機再從他那邊進行讀取。

          在發送數據之前需先設置特征的具有notificaion功能

          private BluetoothGatt mBluetoothGatt;
          BluetoothGattCharacteristic characteristic;
          boolean enabled;
          mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
          BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
          UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
          descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
          mBluetoothGatt.writeDescriptor(descriptor);
          設置完成后回調
          @Override
          public final void onDescriptorWrite(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final int status) {
          //設置成功
          if (status == BluetoothGatt.GATT_SUCCESS) {
          }
          }

          設置成功后就開始發送數據了。

          //將指令放置進特征中

          characteristic.setValue(data);
          //設置回復形式characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);

          //開始寫數據

          mBluetoothGatt.writeCharacteristic(chharacteristic);

          寫入數據成功后回調

          protected void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {

          //發送數據成功啦啦啦

          }

          如何設備回復數據則會回調

          @Override
          public final void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
          }

          關閉客戶端App

          當你的app完成BLE設備的使用后,應該調用close( )),系統可以合理釋放占用資源。

          public void close() {
          if (mBluetoothGatt == null) {
          return;
          }
          mBluetoothGatt.close();
          mBluetoothGatt = null;
          }

          最后分享我在BLE 開發中遇到的坑和一些經驗

          1 在所有藍牙的回調中不要操作UI。我是不會告訴你我是怎么發現這個坑的。

          2 在所有的藍牙回調中不要執行耗時操作。

          3 發送數據要等到上一條數據發送成功后再發下一條數據,畢竟BLE設備運算沒有手機快,這里可以推薦一個開源藍牙連接工具https://github.com/NordicSemiconductor/Android-nRF-Toolbox,里面非常好的對發送的數據做了一個數據隊列。

          4 合理的控制掃描過程,一般出現133錯誤的時候重連就可以先去掃描再去連接。若掃描不到時不要馬上又去掃描,不然你把手機放那一夜,把設備遠離它,第二天回來看手機時會驚喜的發現手機沒電自動關機了

          遇到的坑

          1 斷線重連的時候總是報133錯誤,

          斷線后不要馬上去連接.先掃描設備,掃描到設備后再去連接。

          2 掃描不到設備

          手動關閉藍牙再打開藍牙開關。這個可能是重連里面的掃描引起的,如果設備未在周邊,一直去掃描的話,后來設備在身邊也可能掃描不到設備。如果未能連接設備,也不能一直去掃描。掃描不到設備時說明設備并不到周邊,可以延遲多少時間后再去掃描

          3 連接設備后發送數據,發送數據的回調函數也已經走了。沒有接收到數據

          查看設置特征值的描述值

          descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
          mBluetoothGatt.writeDescriptor(descriptor)的回調里面是不是回調成功了

          4反復斷開藍牙后再重連導致連接失敗

          斷開藍牙后應該調用close()方法釋放資源.連接時應該設置超時,在超時時間內繼續去連接,基本低、中、高端機都能重新連接上。

          5 連接上之后自動斷開連接,重連上之后又自動斷開連接,如此反復。

          我們的BLE設備在某些低端機會遇到這種問題。聽固件工程師說是BLE設備藍牙芯片頻率和手機藍牙頻率問題,需調BLE設備頻率。遇到這種問題APP就束手無策了。

          6 反復操作斷開和連接導致系統藍牙掛掉(無響應)

          基本也是沒有合理釋放資源導致

          7 調用掃描操作導致APP無響應

          查看系統藍牙是否掛掉了。基本和問題6類似

          最后附上一個Nordic 公司開源的Android藍牙開發封裝好的庫地址

          https://github.com/NordicSemiconductor/Android-BLE-Library

          參考:http://www.cnblogs.com/cxk1995/p/5693979.html


          主站蜘蛛池模板: 久久久国产一区二区三区| 成人区人妻精品一区二区不卡视频| 波多野结衣中文一区| 一区二区视频传媒有限公司| 精品一区二区三区东京热| 国产主播一区二区三区在线观看 | 亚洲AV无码一区二区一二区| 精品国产AⅤ一区二区三区4区 | 亚洲av无码一区二区三区网站| 无码精品人妻一区二区三区影院| 国产成人精品一区二区三区免费 | 国产拳头交一区二区| 亚洲天堂一区二区三区四区| 超清无码一区二区三区| 波多野结衣电影区一区二区三区 | 国产福利一区二区三区在线观看| 久久综合一区二区无码| 波多野结衣在线观看一区| 无码人妻av一区二区三区蜜臀| 亚洲综合一区二区精品导航| 亚洲不卡av不卡一区二区| 精品乱子伦一区二区三区| 天天看高清无码一区二区三区| 日韩在线视频一区二区三区| 亚洲AV无码一区二区三区性色| 日本片免费观看一区二区| 色偷偷一区二区无码视频| 亚洲av鲁丝一区二区三区| 亚洲av一综合av一区| 亚洲av无码一区二区三区网站| 日韩亚洲一区二区三区| 亚洲日韩精品一区二区三区无码 | 久久一区不卡中文字幕| 中文字幕一区二区日产乱码| 国产日韩AV免费无码一区二区三区| 美女视频免费看一区二区| 无码人妻一区二区三区在线水卜樱 | 亚洲国产日韩一区高清在线 | 无码毛片视频一区二区本码| 国产精品视频一区二区噜噜 | 亚洲AV日韩综合一区|