1. 程式人生 > >Android開發之藍芽(一)——基於SPP協議藍芽模組通訊

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其實大概過程相差不會很大,但有一些會改變。