Android藍牙開發(一)---基礎知識梳理

前言


在眾多的消費電子類產品中,藍牙作為一種簡易的通訊方式,因此功耗小、體積小、成本低等優勢,被廣泛的應用于耳機、音箱、汽車及醫療器械等領域。作為一種即時技術,不需要特定的器械安裝,固定的設施,而且得益于linux和Android的開源特性,被很多廠家所青睞。

此次分享摘自于項目中的藍牙部分,主要用于實現藍牙耳機的功能,包括電話、音樂、EQ、配對等操作。將分篇章對于android藍牙的開發作介紹說明,并輔以代碼、注釋、通信協議等篇章,力求囊括android簡易的開發流程。


一、Android的藍牙系統


1. Android的藍牙功能

Android包含了對藍牙的協議支持,提供了訪問藍牙功能的API,因此可以很容易的實現:

1) 掃描并連接其他藍牙設備;

2)查詢本地的藍牙適配器;

3)數據通信;

4)管理藍牙連接;

2. Android藍牙相關的類及權限

1)Bluetooth權限

//android的藍牙開發首先需要在AndroidManifest.xml中開通以下權限

<uses-permission android:name="android.permission.BLUETOOTH"/>

<uses-permission?android:name="android.permission.BLUETOOTH_ADMIN"/>

2)BluetoothAdapter;

藍牙適配器,在藍牙Bluetoothsocket連接前,都需要不斷的操作,通過此類用戶可以執行基本的藍牙操作,如初始化設備的搜索,查詢,初始化一個BluetoothDevice類,創建一個BluetoothServerSocket類以監聽其他設備對本機的連接請求等。

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();//建立本地適配器

startDiscovery();//開始遠程設備的搜尋,注冊ACTION_DISCOVERY_STARTED和ACTION_DISCOVERY_FINISHED,確認搜尋結果,返回值為true or false

cancelDiscovery();//取消當前的設備搜索進程,成功返回 true or false

disable();//關閉本地藍牙適配器,異步調用的方法,用戶通過監聽ACTION_STATE_CHANGED的值來獲取隨后的適配器的狀態,成功返回 true or false

enable();//打開本地藍牙適配器,

//為實現友好的提示用戶打開藍牙,建議使用如下方法

Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(intent, 0x01);//0x01代表result_code,可以自行設定

getAddress();//返回本地藍牙適配器的硬件地址,string,例:00:22:44:AA:CC:DD

getName();//獲取本地藍牙適配器的藍牙名稱,即可以在別的藍牙設備上搜索到的名字

setName();//設置藍牙或者本地藍牙適配器的名稱

getBondedDevices();//返回已經匹配(綁定)到本地藍牙適配器的BluetoothDevice類的對象集合;

getRemoteDevice(String address);//根據藍牙地址獲取一個BluetoothDevice對象

checkBluetoothAddress(String address);//驗證藍牙地址是否有效,字母必須全部為大寫,成功返回 true or false

listenUsingRfcommWithServiceRecord(String name, UUID uuid);//根據name,uuid創建一個正在監聽的安全的帶有服務記錄的RFCOMM藍牙端口,并返回一個BluetoothServerSocket

3)BluetoothServerSocket

藍牙設備之間的連接,也可以理解為服務器端與客戶端的連接,其通信的過程可以理解為擁有相同的RFCOMM通道下分別擁有一個連接的BluetoothSocket,然后通過read、write字節流的方法進行通信。在服務器端,使用BluetoothServerSocket類來創建一個監聽服務端口,當調用accept接受連接,會返回一個新的BluetoothSocket進行管理該連接。

accept();//阻塞直到一個連接建立,返回值:已連接的BluetoothSocket,需要在新建立的線程中執行,避免阻塞,使用try ...catch語法,異常將拋出IOException

accept(int timeout);//阻塞直到超時時間內的連接建立,返回值:已連接的BluetoothSocket,需要在新建立的線程中執行,避免阻塞,使用try ...catch語法,異常將拋出IOException

close();//關閉端口,釋放資源

4)BluetoothSocket;

客戶端,使用一個單獨的BluetoothSocket去初始化一個外接連接和管理該連接。

connect();//連接遠程藍牙設備,由于會造成線程阻塞,因此需要新建一個線程中執行此操作,使用try...catch語法,異常將拋出IOException

getInputStream();//通過連接的端口獲得輸入的數據流

BluetoothSocket socket = socket.getInputStream();

getOutputStream();//通過連接的端口獲得輸出的數據流

BluetoothSocket socket = socket.getOutputStream();

getRemoteDevice();//獲得該端口正在連接或是已經連接的遠程設備

5)BluetoothDevice;

通過藍牙搜索可以搜索到BluetoothDevice類的對象集合。

createRfcommSocketToServiceRecord(UUID uuid);//創建并返回一個BluetoothSocket

//首先通過搜索到的device建立一個客戶端的socket,然后通過connect()方法嘗試連接服務器端

BluetoothSocket clientSocket = device.createRfcommSocketToServiceRecord(uuid);

clientSocket.connect();

以上5個知識點是藍牙開發中最常用的基礎知識,此外還包括藍牙搜索設備廣播的建立。

//采用動態方法建立廣播,根據需要可以在onCreate()或者在onResume()方法中注冊廣播

private BroadcastReceiver receiver;

@Override

public void onResume() {

super.onResume();

receiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context,Intent intent) {

String action = intent.getAction();

switch(action)

{

case BluetoothDevice.ACTION_FOUND:

device = intent.getParcelableExtra(BluetoothDevice.EXTRA_NAME);

mlist.add(device);

break;

case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:

case BluetoothAdapter.ACTION_DISCOVERY_STARTED:

break;

}

}

};

filter = newIntentFilter();

filter.addAction(BluetoothDevice.ACTION_FOUND);

filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

//注冊藍牙搜索結果的receiver

mActivity.registerReceiver(receiver,filter);//加上mActivity是因為項目中為fragment與Activity進行交互,如果單純只是為了測試或者沒有fragment,也可以不用加mActivity

}

需要注意的是在使用結束后,需要在onDestroy()中注銷此receiver。

3. Android藍牙中的一些常用知識及使用


3.1 RFCOMM

作為最常用的藍牙端口,是一個面向連接,通過藍牙模塊進行的數據流傳輸方式,也可稱為SPP(Serial Port Profile,串行端口規范)。作為藍牙客戶端與服務器端的socket通道,在設備連接后,僅僅是bondedDevice,還沒有建立通信通道。因此需要在不同的設備的應用程序間建立一個可以通信的路徑。

3.2 UUID

Universally Unique Identifier,通用識別碼,其目的是讓分布式系統中的所有元素,都能有唯一的識別資訊,從而不再需要透過中央控制端來辨別資訊的指定。因此,每個人都可以建立與其他人不沖突的UUID來進行溝通,數據的傳輸,也不需要在考慮數據庫建立時的名字重復問題。理論上只要兩臺設備的UUID一致,即可建立socket。

String ble_uuid = “00000001-0000-1000-8000-00805F9B34AB”;

UUID uuid = UUID.fromString(ble_uuid);

System.out.println("UUID is " + uuid);

3.3 A2DP

之所以提到A2DP,是因為項目中主要是用來實現藍牙耳機的功能(包括音頻、免提電話、播放音樂、設定EQ等)。A2DPProfile定義了高質量音頻數據傳輸的協議和過程,包括立體聲和單聲道數據的傳輸。這里的高質量音頻指的是單聲道(Mono)和立體聲(Sterco)的音頻,主要區別于藍牙SCO鏈路上傳輸的普通語音。A2DP的典型應用是將音樂播放器的音頻數據發送到耳機或音箱。而目前的A2DP值定義了點對點的音頻傳輸。


二、藍牙開發規劃


此次藍牙開發流程,包括對于基礎知識的梳理,通信協議的介紹和撰寫說明,藍牙搜索界面,相關類的封裝,通信過程的開發及代碼講解,會根據筆記的撰寫進行不同程序的完善和改變。

以上知識梳理部分,如有錯誤還請各位大神指出,謝謝。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容