Android開發之藍芽(一)——基於SPP協議藍芽模組通訊
本文意在介紹藍芽開發的主要流程,學習使用藍芽開發一個星期了,寫寫一個星期以來遇到的一些小問題,還有介紹下流程。開發具有基本的通訊功能,本專案主要是用於與藍芽模組的串列埠讀寫功能。
下一篇文章還有Android開發之藍芽(二)——基於BLE協議藍芽模組通訊:
http://blog.csdn.net/wzhworld/article/details/76324738
使用裝置
1、魅族手機
2、藍芽FSC-BT826
3、最終目的是做出能與串列埠除錯助手通訊的功能
基本概念
1、介面卡:
BuletoothAdapter:本地藍芽的介面卡,也就是說當前應用程式所執行的Android裝置上的藍芽。
BuletoothDevice : 遠端的藍芽介面卡,也就是說你要連線的Android裝置的介面卡。。
2、許可權:
android.permission.BLUETOOTH : 一些配置連線藍芽的許可權
android.permission.BLUETOOTH_ADMIN : 進行操作的許可權
3、相關廣播:
BluetoothDevice.ACTION_FOUND:表示可搜尋到附近的藍芽裝置
BluetoothDevice.ACTION_PAIRING_REQUEST:配對請求
BluetoothAdapter.ACTION_STATE_CHANGE:配對狀態改變
後面兩個因為剛剛開始用的時候很迷糊,所以就直接是自動匹配,所以這兩個都沒怎麼用到,不過感覺如果是要做這一方面的話得去了解這些廣播代表什麼。
基本流程
程式寫得有點亂,所以還是說下大概程式寫法,
(1)我是在主活動初始化佈局、藍芽適配、獲取選定藍芽裝置,PS:得先匹配後才能連線
(2)然後開啟一個服務,通過廣播從主活動把選定藍芽物件傳送到服務中。
(3)服務收到之後主要所做的任務就是開啟兩個執行緒,一個是負責對藍芽的socket進行連線,另一個是通過socket進行讀寫,第二個執行緒主要進行的是read,而寫只需要在需要的時候才使用,所以不需要在run中。
(4)非同步執行緒採用訊息機制handler進行成功失敗訊息的傳輸。
1、檢測藍芽以及許可權是否開啟
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> //獲取藍芽介面卡,當沒有開啟時開啟,會回撥一個成功與否的結果 private void initBluetooth() { if(!mBluetoothAdapter.isEnabled()){ Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE); } }
2、此時註冊一個廣播接收器進行接收
//註冊廣播
IntentFilter discoveryFilter = new IntentFilter();
discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
discoveryFilter.addAction(BluetoothDevice.ACTION_FOUND);
discoveryFilter.addAction(BluetoothTools.ACTION_CONNECT_ERROR);
discoveryFilter.addAction(BluetoothTools.ACTION_CONNECT_SUC);
discoveryFilter.addAction(BluetoothTools.ACTION_RECEIVE_DATA);
registerReceiver(mBluetoothReceiver, discoveryFilter);
3、獲取本地介面卡,進行連線
public BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
******
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();//非同步的,不會等待結果,直接返回。
} else if(!mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.startDiscovery();
} //如果裝置正在尋找
4、進行匹配,連線
ClsUtils.createBond(mLastBluetoothDevice.getClass(), mLastBluetoothDevice);
ClsUtils.setPin(mLastBluetoothDevice.getClass(), mLastBluetoothDevice,pin);
使用了一個ClsUtils的工具類,其實就是將一些建立配對什麼的提供一個方法,簡單化。
不過遇到的奇怪的問題就是我createBond建立配對之後,使用Pin配對會自動配對,並沒有說彈出視窗,查了下網上說需要取消視窗什麼的,我試了也是不行,所以就最後沒管了,直接一個自動配對,不過pin是死的,我設了0000,對BT826模組等藍芽模組才有用。
5、在主活動獲取物件之後,傳到服務之中去開啟執行緒。首先是開啟連線的執行緒
//如果匹配成功
if (BluetoothTools.ACTION_PAIRING_SUCC.equals(actionCon)){
Bundle mBundle = intent.getExtras();
BluetoothDevice mBluetoothDevice = mBundle.getParcelable("Pairing_Succ");
BluetoothClientConnThread mThread = new BluetoothClientConnThread(handler,mBluetoothDevice);
mThread.start();//開錢連線執行緒
}
6、進行連線的具體過程
注意連線之前要取消掃描,因為掃描是一個很費時的動作,連線通訊的過程其實與網路的SOCKET相似。
//UUID匹配
socket = serverDevice.createRfcommSocketToServiceRecord(BluetoothTools.PRIVATE_UUID);//藍芽模組的UUID是固定(只對於spp),是00001101-0000-1000-8000-00805F9B34FB
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
socket.connect();
Log.e("Socket connect",String.valueOf(socket.isConnected()));
7、開啟聊天的執行緒
通過廣播讀取editView寫的資料,然後用的是gbk,當時有用過UTF8但是傳輸我記得發生亂碼
//如果鍵盤點選send傳送資料
if(BluetoothTools.ACTION_DATA_TO_GAME.equals(actionCon)){
try {
String editData = (String)intent.getExtras().get("editViewData");
byte[] bytes = editData.getBytes("gbk");
communThread.write(bytes);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
8、通訊執行緒的read、write
bytes = mmInStream.read(buffer);
serviceHandler.obtainMessage(BluetoothTools.MESSAGE_READ_OBJECT, bytes, -1, buffer).sendToTarget();
就是將讀到的buffer通過訊息機制傳回服務,
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
當時也參考了很多的文章,有得是用object傳輸的,但傳的的時候有點問題,傳不了,所以最後都改為使用位元組流傳輸。
基本大概的spp通訊就是這樣一個過程,整體上不算很難,但因為屬於初學階段用起來還不是很熟練,所以學得久一點。下一篇的BLE其實大概過程相差不會很大,但有一些會改變。