android藍牙編程 重點知識 SPP A2DP UUID

藍牙編程很簡單,步驟如下:

(1).獲得本機藍牙設備:BluetoothAdapter mBTAdp = BluetoothAdapter.getDefaultAdapter();;

(2)註冊一個發現設備的回調函數

getActivity().registerReceiver(mBroadcastReceiver,intentFilter);

(3)開始搜索設備:mBTAdp.startDiscovery();在Listview中顯示結果,點擊具體條目時,返回藍牙地址:mAddr 

(4)通過mAddr獲得遠程設備:BluetoothDevice mBTRemoteDev  = mBTAdp.getRemoteDevice(mAddr); //其中mAddr

(5)通過遠程設備的對象,獲得Socket:mBTSocket = mBTDevInThread.createRfcommSocketToServiceRecord(uuid);

網上有很多參考代碼,例如:http://blog.csdn.net/xzongyuan/article/details/39318649。


本文總結研究android藍牙編程中的疑惑:

1.rfcomm有什麼作用?它是藍牙客戶端和服務端的Socket通道。設備pair(配對後),在android中只是bondedDevice,還沒有通信通道。因此,RFCOMM是瞭解藍牙通信的基礎。參考http://www.go-gddq.com/down/2013-06/13062113071155.pdf

RFCOMM是一個簡單傳輸協議,其目的爲了解決如何在兩個不同設備上的應用程序之間保證一條完整的通信路徑,並在它們之間保持一通信段的問題。

2.BluetoothServerSocket是什麼東西?它返回BluetoothSocket,類似於SocketServer,TCP通信業會用到ServerSocket。它的作用就是監聽其他藍牙設備的接入,一旦有藍牙設備主動發起建立RFCOMM信道,它就會返回一個"新的"對應的BluetoothSocket。

使用辦法,因爲是監聽,所以函數名是listen

BluetoothServerSocket tmp ;
tmp =mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
mmServerSocket =tmp;
mmServerSocket調用accept進行監聽,是阻塞操作,一旦有設備發起請求,就會返回一個Socket,這個Socket也是阻塞操作,因此需要新建一個獨立線程進行處理。

01 while(true){
02  BluetoothSocket  socket;
03             socket = mmServerSocket.accept();                 // If a connection was accepted        
04   if (socket!= null){              
05     // Do work to manage the connection (in a separate thread)               
06     manageConnectedSocket(socket);               
07     mmServerSocket.close();              
08     break;       
09    }    
10 }



3.UUID是什麼?一個uuid對應一種service,在藍牙4.0的datasheet中有定義UUID的格式,哪個bit代表什麼功能都有清楚定義,而且有很多常用的服務已經根據datasheet定義好了值,所以你上網會查到UUID表;不過,理論上,只要兩臺設備UUID是一致的,就能建立socket。統一格式,只是提高設備間的兼容性,避免不同service碰巧被定義爲相同的uuid了。android提供的Sample——BluetoothChat就是自定義的。而一般情況,還是得符合UUID的規範,例如我設計的SPP協議通信,這是藍牙數據傳輸的基本協議,我只需要查到SPP的uuid爲:

static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";

我就不用管其他設備的情況了。例如我設計的一塊開發板,壓根就沒提供uuid,只是提供spp的api,如果沒有統一的uuid,我就無法進行通信了。


4.藍牙傳輸和藍牙音頻如何同時開啓?這是我的一個疑問,我用createRfcommSocketToServiceRecord創建了一個Socket鏈接請求,但是成功後,我只能發數據,不能把手機音頻傳到開發板。我在想,必定有某個地方創建了音頻Socket,可能是A2DP,使得音頻可以順利傳輸。經過百般搜索,終於找到個不錯的鏈接

https://www.bluetooth.org/zh-cn/specification/assigned-numbers/service-discovery

AudioSource 0x110A 高級音頻分發配置文件(A2DP) 服務類
AudioSink 0x110B 高級音頻分發配置文件(A2DP) 服務類
SerialPort 0x1101 串口配置文件(SPP)
注:SPP 1.0版中的SDP記錄範例並不包含BluetoothProfileDescriptorList屬性,但部分實施中也可將此UUID用於配置文件標識符。
服務類/配置文件
從上面的定義可以看到,AudioSource和AudioSink就是A2DP的配置名稱,我把SPP的UUID改一下就得到A2DP的UUID了

static final String SPP_UUID                = "00001101-0000-1000-8000-00805F9B34FB";

static final String A2DP_SRC_UUID  = "0000110A-0000-1000-8000-00805F9B34FB";
static final String A2DP_SINK_UUID  = "0000110B-0000-1000-8000-00805F9B34FB";


5.Socket connect faild怎麼處理?我之前在用getBondedDevices獲得已經pair的設備,然後連接,當只有一臺設別時,不需要辨別。但當我安裝APP到一臺已經配對了2個設備的Tablet上,發現,Socket Connect time out 了。原因是,getBondedDevice返回的是一個BluetoothDevice設備Set,我剛好獲得另外一個BluetoothDevice(不是我想連接的那臺),而另一臺設備藍牙沒打開,以至於我創建的Socket連接不上。


6.怎麼同時啓動SPP和音頻A2DP功能?研究了1天,終於找到辦法了,用反射機制把Android隱藏API調用出來,即可,實現代碼:

http://blog.csdn.net/xzongyuan/article/details/39344953


參考資料:

如果能翻牆,最好去官網看Reference API,講的比較全。

http://blog.csdn.net/flyfish10000/article/details/5796168

http://blog.csdn.net/xzongyuan/article/details/39318649

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章