android ble藍芽開發略解

來源:互聯網
上載者:User

標籤:

Android 藍芽4.0開發

 

1、  許可權和相關屬性

“android:required="true"表示apk只有在具有bluetooth_le屬性的系統裡運行,這個4.3之前android系統沒有

<uses-featureandroid:name="android.hardware.bluetooth_le"android:required="true"/>

  

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

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

 

2、  程式開媽操作藍芽之前,先判斷ble是否支援

if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {

            Toast.makeText(this,R.string.ble_not_supported, Toast.LENGTH_SHORT).show();

            finish();

        }

3、  開啟、關閉藍芽

先擷取藍芽的一個代理

final BluetoothManager bluetoothManager =

                (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);

       mBluetoothAdapter = bluetoothManager.getAdapter();

 

發intent通知系統開啟藍芽

if(!mBluetoothAdapter.isEnabled()) {

            if (!mBluetoothAdapter.isEnabled()){

                Intent enableBtIntent = newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

               startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

            }

        }

 

也可以使用 enable 和disable函數來開啟關閉

4、  搜尋ble裝置

mHandler.postDelayed(newRunnable() {

                @Override

                public void run() {

                    mScanning = false;

                   mBluetoothAdapter.stopLeScan(mLeScanCallback);

                   

                }

            }, SCAN_PERIOD);

 

            mScanning = true;

           mBluetoothAdapter.startLeScan(mLeScanCallback);

 

//SCAN_PERIOD是10000,表示每次的搜尋時間為10秒

需要注意的是mLeScanCallback,在4.3之前的api是通過註冊廣播來處理搜尋時發生的一些事件,而支援ble的新的api中,是通過回調的方式來處理的,mLeScanCallback就是一個介面對象,看一下實現:

privateBluetoothAdapter.LeScanCallback mLeScanCallback =

            newBluetoothAdapter.LeScanCallback() {

 

        @Override

        public void onLeScan(finalBluetoothDevice device, int rssi, byte[] scanRecord) {

            runOnUiThread(new Runnable() {

                @Override

                public void run() {

                    mLeDeviceListAdapter.addDevice(device);

                   mLeDeviceListAdapter.notifyDataSetChanged();

                }

            });

        }

};

5、  串連

4.3之前的api是通過socket方式在藍芽之間互相通訊,串連的結果是返回一個socket對象

在支援4.0藍芽的新的api中,返回的是BluetoothGatt對象

可以將BluetoothGatt對象看成是遠程裝置的一個代理

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

 

mGattCallback是一個抽象類別對象,之前的廣播形式,在新的api中都改成了回調

BluetoothGattCallback抽象類別,只有9個方法,字面意思就都可以看懂,在處理串連事件上,需要處理方法:

public voidonConnectionStateChange(BluetoothGatt gatt, int status,

                                        intnewState)

 

條件:if (newState ==BluetoothProfile.STATE_CONNECTED)

else if (newState ==BluetoothProfile.STATE_DISCONNECTED)分別表示已串連和已斷開

6、 通訊

這一點與之前形式上完全不一樣了

BLE分為三部分Service、Characteristic、Descriptor,這三部分都由UUID作為唯一標示符。一個藍芽4.0的終端可以包含多個Service,一個Service可以包含多個Characteristic,一個Characteristic包含一個Value和多個Descriptor,一個Descriptor包含一個Value。

在串連上某個終端後,可以將其每個結點的UUID全部列印出來,但每個結點不是都能讀寫。

一般來說,Characteristic是手機與BLE終端交換資料的關鍵,Characteristic有較多的跟許可權相關的欄位,例如PERMISSION和PROPERTY,而其中最常用的是PROPERTY,本文所用的BLE藍芽模組竟然沒有標準的Characteristic的PERMISSION。Characteristic的PROPERTY可以通過位元運算符組合來設定讀寫屬性,例如READ|WRITE、READ|WRITE_NO_RESPONSE|NOTIFY,因此讀取PROPERTY後要分解成所用的組合

我是這麼去和ble終端通訊的:

得到某個service的對象

BluetoothGattService linkLossService =mBluetoothGatt

                                      .getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));

一般說來,ble裝置都帶有幾個標準的服務,其UUID已經定義好了,這些結點裡的值只能讀了,因為我一個一個試過了,終於找到了我的裝置裡可以讀寫的服務,其中49535343-fe7d-4ae5-8fa9-9fafd205e455就是對應這個服務的

 

擷取此服務結點下的某個Characteristic對象

BluetoothGattCharacteristic alertLevel =linkLossService.getCharacteristic(UUID.fromString("49535343-8841-43f4-a8d4-ecbe34729bb3"));

一般供應商會給出多個Characteristic,你需要找到到底哪個才是讓你去寫的,怎麼找需要看對應的終端的一些開發文檔之類的,在這裡我經過測試已經找到我要的了

 

設定要寫的值

alertLevel.setValue(values_on);

這裡的values_on是一個byte數組

 

status = mBluetoothGatt.writeCharacteristic(alertLevel);

status如果為true,表示寫操作已經成功執行,BluetoothGattCallback抽象類別的一個方法會被執行,如果剛好你又重寫了這個方法,就可以列印一些訊息了

public void onCharacteristicWrite(BluetoothGatt gatt,

           BluetoothGattCharacteristiccharacteristic, int status)

 

讀某個Characteristic

public void readCharacteristic(BluetoothGattCharacteristiccharacteristic) {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {

            Log.w(TAG, "BluetoothAdapter not initialized");

            return;

        }

        mBluetoothGatt.readCharacteristic(characteristic);

}

 

如果成功,資料會在下面的方法回調中傳進來

public voidonCharacteristicRead(BluetoothGatt gatt,

                                        BluetoothGattCharacteristic characteristic,

                                         int status)

 

當終端有資料要傳過來的時候,表面上正常的話,手機這邊下面的方法會被調用

public voidonCharacteristicRead(BluetoothGatt gatt,

                                        BluetoothGattCharacteristic characteristic,

                                         intstatus)

這個也是可以控制的,設定descriptor的value不同,可以控制這個重寫的方法是否會被調用,沒有測試其他的裝置,感覺這個應該是會對應不同的裝置,具體設定的地方會有不同,在我這邊是這麼操作的:

public void enableNotification(boolean b)

    {

    if(b)

    {

               BluetoothGattService service =mBluetoothGatt

                             .getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));

             BluetoothGattCharacteristicale =service.getCharacteristic(UUID.fromString("49535343-1E4D-4BD9-BA61-23C647249616"));

             booleanset = mBluetoothGatt.setCharacteristicNotification(ale, true);

             Log.d(TAG," setnotification = " + set);

             BluetoothGattDescriptordsc =ale.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));

             byte[]bytes = {0x01,0x00};

        dsc.setValue(bytes);

        boolean success =mBluetoothGatt.writeDescriptor(dsc);

        Log.d(TAG, "writing enabledescriptor:" + success);

    }

    else

    {

               BluetoothGattService service =mBluetoothGatt

                             .getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));

             BluetoothGattCharacteristicale =service.getCharacteristic(UUID.fromString("49535343-1E4D-4BD9-BA61-23C647249616"));

             booleanset = mBluetoothGatt.setCharacteristicNotification(ale, false);

             Log.d(TAG," setnotification = " + set);

             BluetoothGattDescriptordsc =ale.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));

             byte[]bytes = {0x00, 0x00};

        dsc.setValue(bytes);

        boolean success =mBluetoothGatt.writeDescriptor(dsc);

        Log.d(TAG, "writing enabledescriptor:" + success);

    }

   

    }

7、 總結

網上的一些資料大都以上面的命名來標識自己的文檔,有必要解釋一下,應該分開來看這個命題:

android指的安裝的4.3及以上版本的android系統的裝置

4.0藍芽指的藍芽晶片使用4.0協議的裝置

這種開發的一種標準用處是:用4.3以上android版本的手機,與4.0藍芽穿戴式裝置進行通訊

按網上的一種中央與周邊的說法,手機就是中央,4.0藍牙裝置就中周邊

如果要開發4.0藍芽,應該知道4.0藍芽具有高速、低功耗的優點,這些優點對手機的提升不大,但對其他一些終端裝置的提升就比較大。

有意思的是,android對與4.0藍芽通訊的封裝,不需要本身裝置的藍芽晶片是4.0協議的藍芽晶片

於是android 藍芽4.0開發的這麼一個“大環境”下的真實情景就是:一個沒有必要擁有藍芽4.0協議的藍芽晶片的android4.3以上系統的手機,與一些4.0藍芽協議的藍芽晶片裝置終端的故事

以上是一些事實,以下是一些猜想

1、 藍芽4.0與之前版本協議之間可以通訊,說明:4.0藍芽協議並不是修改的無線波的調製與解調,而是修改的資料的組成

2、 對藍芽4.0協議的支援,是由google提出的,而不是各個手機廠商提出的,說明:android系統在軟體上可以一致對待不同的藍芽晶片,不同的藍芽晶片對同一段資料的調製解調結果是一樣的,於是在這段資料通過串口傳到手機主控的時候,也是一樣的,在這個環境裡,藍芽晶片只是一個數據機,android封裝了對資料全部的處理。

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.