Android BLE開發——Android手機與BLE終端通訊初識,androidble

來源:互聯網
上載者:User

Android BLE開發——Android手機與BLE終端通訊初識,androidble

藍芽BLE官方Demo:   http://download.csdn.net/detail/lqw770737185/8116019
參考部落格地址:    http://www.eoeandroid.com/thread-563868-1-1.html?_dsign=843d16d6

 

     裝置:MX5手機一台,農藥殘留檢測儀一台(BLE終端裝置)

     目的:實現手機控制儀器,如發送列印指令,儀器能進行列印操作等

 

      關於如何開啟藍芽,配置相關許可權,搜尋BLE裝置等步驟網上有很多資料,這裡就不多做作解釋了,本文主要講通訊方面的內容。需要注意的是搜尋BLE裝置的結果是非同步返回的,在BluetoothAdapter.LeScanCallback這個回調中返回,並且搜尋過程是一個非常耗電的過程,所以我們應該做好相應處理,例如可以讓它搜尋10s就停止搜尋等。

      在我們理解Android裝置與BLE終端裝置通訊過程之前,我們需要來先瞭解幾個類:

      BluetoothGatt:BluetoothGatt 是我們用的最多,也是我們最重要的一個類,為了儘可能通俗的理解,這裡我們可以把它看成Android手機與BLE終端裝置建立通訊的一個管道,只有有了這個管道,我們才有了通訊的前提。

      BluetoothGattService:藍牙裝置的服務,在這裡我們把BluetoothGattService比喻成班級。而Bluetoothdevice我們把它比喻成學校,一個學校裡面可以有很多班級,也就是說我們每台BLE終端裝置擁有多個服務,班級(各個服務)之間通過UUID(唯一識別碼)區別。

      BluetoothGattCharacteristic: 藍牙裝置所擁有的特徵,它是手機與BLE終端裝置交換資料的關鍵,我們做的所有事情,目的就是為了得到它。在這裡我們把它比喻成學生,一個班級裡面有很多個學生,也就是說我們每個服務下擁有多個特徵,學生(各個特徵)之間通過UUID(唯一識別碼)區別。

      總結:當我們想要用手機與BLE裝置進行通訊時,實際上也就相當於我們要去找一個學生交流,首先我們需要搭建一個管道,也就是我們需要先擷取得到一個BluetoothGatt,其次我們需要知道這個學生在哪一個班級,學號是什麼,這也就是我們所說的serviceUUID,和charUUID。這裡我們還需要注意一下,找到這個學生後並不是直接和他交流,他就好像一個中介一樣,在手機和BLE終端裝置之間協助這兩者傳遞著資訊,我們手機所發資料要先經過他,在由他傳遞到BLE裝置上,而BLE裝置上的返回資訊,也是先傳遞到他那邊,然後手機再從他那邊進行讀取。

      Android手機與BLE終端裝置通訊結果都是以回調的形式返回,如下是幾個常見的返回回調(可見於官方Demo的BluetoothLeservice類):

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {        //串連狀態改變的回調        @Override        public void onConnectionStateChange(BluetoothGatt gatt, int status,                int newState) {            if (newState == BluetoothProfile.STATE_CONNECTED) {                // 串連成功後啟動服務發現                Log.e("AAAAAAAA", "啟動服務發現:" + mBluetoothGatt.discoverServices());            }        };        //探索服務的回調        public void onServicesDiscovered(BluetoothGatt gatt, int status) {            if (status == BluetoothGatt.GATT_SUCCESS) {                                                    Log.e(TAG, "成功探索服務");                           }else{                   Log.e(TAG, "服務發現失敗,錯誤碼為:" + status);                        }        };                         //寫操作的回調        public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {            if (status == BluetoothGatt.GATT_SUCCESS) {                  Log.e(TAG, "寫入成功" +characteristic.getValue());                       }               };                 //讀操作的回調       public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {            if (status == BluetoothGatt.GATT_SUCCESS) {                    Log.e(TAG, "讀取成功" +characteristic.getValue());                    }                }                      //資料返回的回調(此處接收BLE裝置返回資料)      public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {                };            };      }

一、串連藍芽BLE終端裝置

       在我們開啟藍芽,掃描發現想要串連的裝置後,接下來要做的,當然就是去串連它了,串連方法很簡單,我們一句代碼就可以實現了(如下)。可以發現,當我們開始串連BLE終端裝置的時候,串連方法就自動就幫我們返回了一個BluetoothGatt對象了,前面我們說到BluetoothGatt是我們最重要的一個類,它相當於一個管道,是我們建立通訊的前提:(這裡面有三個參數,第一個參數是內容物件,第二個參數是是否自動連接,這裡設定為false,第三個參數就是上面的回調方法)

mBluetoothGatt = device.connectGatt(this, false, mGattCallback);

串連成功與否都會通過下面這個回調來告訴我們:

// 串連狀態改變的回調        @Override        public void onConnectionStateChange(BluetoothGatt gatt, int status,                int newState) {                        //代表串連成功,此處我們可以發送一個廣播回去告訴activity已成功串連            if (newState == BluetoothProfile.STATE_CONNECTED) {                //串連成功後啟動服務發現                Log.e("AAAAAAAA", "啟動服務發現:" + mBluetoothGatt.discoverServices());            }        }

二、啟動服務發現

 串連成功後,我們就要去尋找我們所需要的服務,這裡需要先啟動服務發現,使用一句代碼即可:

mBluetoothGatt.discoverServices() ;

啟動服務發現,它的結果也是通過回呼函數返回:

        // 探索服務的回調        public void onServicesDiscovered(BluetoothGatt gatt, int status) {                  //成功探索服務後可以調用相應方法得到該BLE裝置的所有服務,並且列印每一個服務的UUID和每個服務下各個特徵的UUID            if (status == BluetoothGatt.GATT_SUCCESS) {                    List<BluetoothGattService> supportedGattServices =mBluetoothGatt.getServices();                    for(int i=0;i<supportedGattServices.size();i++){                       Log.e("AAAAA","1:BluetoothGattService UUID=:"+supportedGattServices.get(i).getUuid());                       List<BluetoothGattCharacteristic> listGattCharacteristic=supportedGattServices.get(i).getCharacteristics();                       for(int j=0;j<listGattCharacteristic.size();j++){                                Log.e("a","2:   BluetoothGattCharacteristic UUID=:"+listGattCharacteristic.get(j).getUuid());                                    }                                 }            } else {                Log.e("AAAAA", "onservicesdiscovered收到: " + status);            }        }

我們也可以通過調用下面方法得知每個特徵所具有的屬性:可讀或者可寫或者具備通知功能或者都具備等

// 迴圈遍曆服務以及每個服務下面的各個特徵,判斷讀寫,通知屬性        for (BluetoothGattService gattService :supportedGattServices) {            List<BluetoothGattCharacteristic> gattCharacteristics =supportedGattServices.getCharacteristics();            for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {                int charaProp = gattCharacteristic.getProperties();                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {                    // Log.e("nihao","gattCharacteristic的UUID為:"+gattCharacteristic.getUuid());                    // Log.e("nihao","gattCharacteristic的屬性為:  可讀");                }                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {                    // Log.e("nihao","gattCharacteristic的UUID為:"+gattCharacteristic.getUuid());                    // Log.e("nihao","gattCharacteristic的屬性為:  可寫");                }                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {                    // Log.e("nihao","gattCharacteristic的UUID為:"+gattCharacteristic.getUuid()+gattCharacteristic);                    // Log.e("nihao","gattCharacteristic的屬性為:  具備通知屬性");                }            }        }

三、擷取Characteristic

       之前我們說過,我們的最終目的就是擷取Characteristic來進行通訊,正常情況下,我們可以從硬體工程師那邊得到serviceUUID和characteristicUUID,也就是我們所比喻的班級號和學號,以此來獲得我們的characteristic,但如果我們無法得知這兩個所需的UUID時,我們也可以通過上一步的方法來擷取(列印所有特徵UUID,取出自己想要的特徵)。這次實驗我就是通過此方法獲得,但是通過列印日誌發現,雖然我這邊的BLE終端它每個服務下的所有特徵都具有可讀可寫可通知屬性,但是只有characteristicUUID="0000ffe1-0000-1000-8000-00805f9b34fb"這個特徵UUID能進行通訊,它對應的serviceUUID="0000ffe0-0000-1000-8000-00805f9b34fb",暫且就先用這個,反正一個能用就行。假設我們在知道serviceUUID和characteristicUUID的前提下,我們就可以通過下面代碼擷取相應特徵值:  

BluetoothGattService service = mBluetoothGatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"));BluetoothGattCharacteristic characteristic= service.getCharacteristic(UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"));

四、開始通訊

       我們在得到一個相應的特徵以後,接下來就可以開始讀寫操作進行通訊了。

      a.讀操作,讀操作比較簡單,只需將相應的特徵值傳入即可得到該特徵值下的資料,如下代碼:       

mBluetoothGatt.readCharacteristic(characteristic);

讀取的結果通過onCharacteristicRead回調返回:(通過characteristic.getValue()就可以得到讀取到的值了)

    // 讀操作的回調        public void onCharacteristicRead(BluetoothGatt gatt,                BluetoothGattCharacteristic characteristic, int status) {            if (status == BluetoothGatt.GATT_SUCCESS) {                Log.e(TAG, "讀取成功" +characteristic.getValue());            }        }

       b.寫操作,寫操作是我們的重點,我們可以通過向characteristic寫入指令(發送指令)以此來達到控制BLE終端裝置的目的:

                           //將指令放置進特徵中                            characteristic.setValue(new byte[] {0x7e, 0x14, 0x00, 0x00,0x00,(byte) 0xaa});                           //設定回複形式                           characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);                           //開始寫資料                           mBluetoothGatt.writeCharacteristic(chharacteristic);

註:與儀器通訊,我們這裡發送的是16進位的資料,發送的時候需要先將其裝載到byte[]數組中,例如我發送 7e 14 00 00 00 aa這個指令,我需要把它轉化為ew byte[] {0x7e, 0x14, 0x00, 0x00,0x00,(byte) 0xaa }這樣去發送,因為BLE傳輸過程每次最大隻能傳輸20個位元組,所以如果發送的指令大於20位元組的話要分包發送,例如現在要發送28個位元組的,可以先write(前20個位元組),開啟線程sleep(幾十毫秒)後在write(後面8個位元組)

五、BLE終端裝置返回資料
       當我們向BLE終端裝置寫入指令時,如果寫入成功並且指令也正確,我們就會獲得相應的響應指令,在下面這個回調中我們可以得到BLE裝置返回回來的響應指令(通過characteristic.getValue()取出返回資料):

    // 資料返回的回調(此處接收機器返回資料並作處理)        public void onCharacteristicChanged(BluetoothGatt gatt,                BluetoothGattCharacteristic characteristic) {            Log.e("AAAAAAAA",characteristic.getValue());        };

接收到返回資料的前提是我們設定了該特徵具有Notification功能,所以完整的寫作業碼應該是這樣的(注意設定特徵Notification的代碼要放在最前):

           mBluetoothGatt.setCharacteristicNotification(characteristic,true)           //將指令放置進來           characteristic.setValue(new byte[] {0x7e, 0x14, 0x00, 0x00,0x00,(byte) 0xaa});           //設定回複形式           characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);           //開始寫資料           mBluetoothGatt.writeCharacteristic(chharacteristic);

  以上就是自己對Android手機與BLE裝置通訊一些初步認識,如果有哪裡說的不正確,還請指正。

                             

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.