通信硬體NFC的文章,雖然可以在Android系統中通過非直接接觸的形式與支持NFC硬體的設備通信,但是也只能互動一些簡短的標簽內容,對大量的持續性資料,卻并不能很好的支持,因此針對這個弊端,可以考慮使用支持Bluetooth技術的硬體,
Android系統支持傳統的Bluetooth技術,其實作功能不僅可以傳輸資料,還可以傳輸并執行遠程控制指令,在Android4.3 即API 18 及以后的版本中,低功耗的Bluetooth技術(簡稱為BLE)取自傳統Bluetooth的核心功能,可以更省功耗并支持資料傳輸功能,在傳統藍牙技術中,應用程式所持有的藍牙設備可以作為藍牙服務端,開啟藍牙等待處理其他藍牙設備的接入請求;也可以作為藍牙客戶端,開啟藍牙查找附近的藍牙設備并請求接入,而在BLE技術中,應用程式所持有的藍牙設備只能作為GATT客戶端,連接其他類似藍牙耳機等BLE設備,下面應用程式將會以這三種身份分別說明,
權限宣告
使用Bluetooth技術,需要在清單檔案中宣告藍牙相關權限,申請權限使用<uses-permission />標簽,并設定其android:name屬性為對應的權限名,藍牙相關權限中主要有三種權限,申請后可分別對應執行不同功能,首先是可以執行藍牙通信的基礎權限,其值為Manifest.permission.BLUETOOTH="android.permission.BLUETOOTH";在需要通過藍牙獲取位置資訊的應用程式中,還需要獲取位置權限,其值為Manifest.permission.ACCESS_FINE_LOCATION="android.permission.ACCESS_FINE_LOCATION";另外如果需要使用藍牙的遠程控制功能,需要藍牙管理員權限,其值為Manifest.permission.BLUETOOTH_ADMIN="android.permission.BLUETOOTH_ADMIN",
使用流程
由于一個Android系統的設備上只能使用唯一的一個藍牙硬體,因此應用程式中可以通過android.bluetooth.BluetoothAdapter藍牙配接器操作底層的藍牙硬體,
設定藍牙
呼叫BluetoothAdapter中的靜態方法getDefaultAdapter()可以獲取到BluetoothAdapter藍牙配接器物件,但是,從Android 12即API 31開始就廢棄了上述方法,取而代之的是借助android.bluetooth.BluetoothManager藍牙管理類,在能獲取到Context背景關系環境類物件的位置,呼叫其getSystemService(String name)方法,傳入引數 name 值為Context.BLUETOOTH_SERVICE="bluetooth",可以獲取到BluetoothManager藍牙管理類的實體化物件,進而呼叫該物件的getAdapter()方法獲取已經實體化的BluetoothAdapter藍牙配接器物件,
對于不支持藍牙硬體的設備,得到的藍牙配接器物件為null,因此記得在應用程式中做非空判斷的相關操作!
在支持藍牙的設備上得到BluetoothAdapter物件后,還要確保設備已經開啟了藍牙功能,呼叫該物件的isEnabled()方法,根據回傳的boolean型別結果,判斷該設備是否已經正常開啟了藍牙功能;如果藍牙處于未啟用狀態,還要通過呼叫Context背景關系環境物件的startActivityForResult(Intent intent, int requestCode)方法跳轉到藍牙功能開啟界面,而這里傳入的引數 intent 則是標記為藍牙界面的Intent意圖物件,在該物件中設定其 action 值為BluetoothAdapter.ACTION_REQUEST_ENABLE ="android.bluetooth.adapter.action.REQUEST_ENABLE",在跳轉到藍牙功能界面后,需要由用戶手動選擇開啟藍牙,并回傳當前界面后,才能繼續執行后續操作,
藍牙客戶端查找其他藍牙設備
在設定藍牙等操作之后,就是查找該設備附近范圍內其他開啟藍牙功能的設備了,可以直接呼叫BluetoothAdapter物件的startDiscovery()方法來開啟查找附近設備的功能,但是在發現設備后,系統會通過廣播的形式發送已發現的設備資訊給應用程式,所以還需要在某個自定義界面Activity或者服務Service中,注冊BroadcastReceiver以接收該廣播,
注冊廣播的方式可以回顧BroadcastReceiver動態注冊部分內容,這里只是需要創建的IntentFilter意圖過濾物件中的引數 action 值為BluetoothDevice.ACTION_FOUND="android.bluetooth.device.action.FOUND",同時在自定義的BroadcastReceiver中處理收到的onReceive(Context context, Intent intent)方法中,對引數 intent 的getParcelableExtra(String name)方法,并設定 name 值為BluetoothDevice.EXTRA_DEVICE="android.bluetooth.device.extra.DEVICE",可以獲得android.bluetooth.BluetoothDevice藍牙硬體設備類物件,在該物件中可以獲取查找到的藍牙硬體相關資訊,
在查找到設備后,要及時呼叫BluetoothAdapter物件的cancelDiscovery()方法關閉查找功能,否則設備的藍牙硬體會一直占用cpu資源并消耗電量,而且在后續的建立連接及資料傳輸時,也會由于藍牙發現功能的開啟占用大量帶寬而影響后續操作效率,
對于之前已經連接配對過的設備,就不需要通過上述查找藍牙的方式發現設備了,可以通過呼叫BluetoothAdapter物件的getBondedDevices()方法,直接獲取已配對過的藍牙設備,回傳BluetoothDevice物件組成的Set集合,
藍牙服務端等待其他設備連接請求
在設定藍牙操作后,如果想將該設備作為被發現的設備等待連接,需要啟動藍牙的可檢測功能,與開啟藍牙功能界面的方法類似,呼叫Context背景關系環境物件的startActivityForResult(Intent intent, int requestCode)方法跳轉到啟動藍牙可檢測性功能界面,傳入的引數 intent 意圖物件中,設定的 action 值為BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE="android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";另外可以通過putExtra(String name, int value)設定可檢測時間,其引數 name 值為BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION="android.bluetooth.adapter.extra.DISCOVERABLE_DURATION",而引數 value 值為int型別的數值,單位為秒,
同樣在跳轉到藍牙可檢測性功能界面后,需要由用戶手動確認開啟,才能等待被其他藍牙設備查找發現,同時不管用戶確認開啟或取消開啟功能,都會將結果回呼到Context背景關系環境所代表的原啟動界面Activity中的onActivityResuslt(int requestCode, int resultCode, Intent data)方法中,
藍牙Gatt客戶端查找其他BLE設備
在設定藍牙操作后,如果只是想查找附近的BLE設備并建立連接,則需要先拿到android.bluetooth.le.BluetoothLeScannerBLE掃描類物件,通過BluetoothAdapter物件的getBluetoothLeScanner()方法,可以得到BluetoothLeScannerBLE掃描類物件,之后借助該物件的startScan(ScanCallback callback)等系列方法,開始掃描查找附近的BLE設備,在查找到符合條件的設備后,會回呼android.bluetooth.le.ScanCallback型別的引數 callback 物件中的onScanResult(int callbackType, ScanResult result)方法,并將結果保存在android.bluetooth.le.ScanResult掃描結果型別的引數 result 物件中,在ScanResult物件中,可以獲得連接的BLE設備BlutoothDevice物件及連接所使用的協議功能等資訊,
掃描查找到BLE設備后,及時呼叫BluetoothLeScanner物件的stopScan(ScanCallback callback)方法,引數 callback 與上文開始查找附近BLE設備方法中的引數相同,以停止當前藍牙掃描查找功能,
連接藍牙
在上述查找藍牙或藍牙可檢測功能開啟后被其他設備連接后,都會得到對方的BlutetoothDevice藍牙設備類物件,通常,應用程式所在設備查找到其他藍牙設備后,可以主動向設備建立連接請求;而當應用程式所在設備開啟藍牙可檢測功能等待其他設備查找到時,只能被動的開啟連接服務,等待處理其他設備的連接請求,
藍牙客戶端發起連接請求
對于主動發起藍牙連接請求的方式,由得到的BluetoothDevice物件呼叫createRfcommSocketToServiceRecord(UUID uuid)方法,可以創建遠程socket連接,引數 uuid 是自定義的java.util.UUID唯一索引類物件,該值必須與后文提到的被動等待連接的藍牙設備中的監聽服務中的唯一索引值一致,該方法會回傳android.bluetooth.BluetoothSocket類用以保存創建的遠程藍牙socket連接,
在得到BluetoothSocket物件后,直接呼叫該物件的connect()方法發起連接請求,該方法呼叫后會一直等待連接的建立,只有建立連接后才會正常回傳并執行后續操作,否則,如果請求超時或連接失敗,該方法會拋出java.io.IOException例外,
藍牙服務端等待處理連接
對于被動等待建立連接的方式,由得到的BluetoothDevice物件呼叫listenUsingRfcommWithServiceRecord(String name, UUID uuid)方法,建立持續監聽服務,引數 name 是為該服務定義的名字;引數 uuid 是監聽的唯一索引值,其值與上文中主動發起藍牙連接請求是創建遠程socket連接所傳入的引數一致,該方法回傳android.bluetooth.BluetoothServerSocket藍牙連接的服務端socket類,用以保存在等待建立連接時的socket物件,
在得到BluetoothServerSocket物件后,直接呼叫該物件的accept()方法監聽連接請求,該方法呼叫后也會一致等待監聽狀態,只有監聽到匹配的連接請求后,才會回傳BluetoothSocket物件,否則,如果連接失敗,該方法同樣會拋出java.io.IOException例外,
對于上述兩種建立連接方式執行之后,便可以通過BluetoothSocket物件在藍牙客戶端和服務端之間傳輸資料,該物件的getInputStream()和getOutputStream()方法可以分別獲取socket連接的InputStream資料輸入流物件和OutputStream資料輸出流物件,可以借助InputStream資料輸入流的read()系列方法,從socket連接中讀取資料到應用程式中,反之借助OutputStream資料輸出流的write()系列方法,將應用程式中的資料寫入到socket連接中,同樣地,這里的資料輸入流的讀取系列方法會一直處于等待讀取狀態,直到讀到指定長度資料后才會回傳結果,而資料輸出流的寫入系列方法,會在對方資料輸入流讀取慢導致寫入快取滿時處于一直等待寫入狀態,直到指定資料完全寫入才會回傳結果,
在BluetoothServerSocket或BluetoothSocket物件傳輸資料結束后,需要分別呼叫他們的close()方法關閉連接,防止遠程socket連接一直處于占用資源狀態,
Gatt客戶端連接BLE設備
對于Gatt客戶端連接方式,由得到的BluetoothDevice物件呼叫connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)系列方法連接BLE設備的Gatt服務端,引數 context 是當前應用程式所在的背景關系環境物件,引數 autoConnect 標識是否在連接該設備后自動建立Gatt服務連接,引數 callback 是建立Gatt服務連接后的回呼android.bluetooth.BluetoothGattCallback抽象類,
在初次連接其他BLE設備的Gatt服務端時,會回呼引數 callback 中的onServicesDiscovered(BluetoothGatt gatt, int status) 方法,而當已建立的Gatt連接狀態發生改變時,會回呼引數 callback 中的onConnectionStateChange(BluetoothGatt gatt, int status, int newState)方法,其他連接狀態也會對應BluetoothGattCallback類中的相關方法,
在BluetoothGattCallback抽象類的回呼方法中,Gatt服務連接資訊是通過android.bluetooth.BluetoothGatt類的引數 gatt 來傳遞的,通過BluetoothGatt物件的相關方法,可以執行Gatt客戶端的連接及協議控制等操作,具體可需根據應用程式需求實作,只是記得在執行完相關操作后,呼叫引數 gatt 的close()方法關閉連接,
————————————————————————————————————————————————————————
———————————————————————————————轉載請注明出處:白少木丿—————————————————轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/423193.html
標籤:其他
