久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Android 與BLE設(shè)備通訊

 杰出天下 2018-08-13

 

一,、基本介紹

BLE全稱Bluetooth Low Energy即低功耗藍(lán)牙,。

Android 4.3(API Level 18)開始引入核心功能并提供了相應(yīng)的 API, 應(yīng)用程序通過這些 API 掃描藍(lán)牙設(shè)備,、查詢 services,、讀寫設(shè)備的 characteristics(屬性特征)等操作。

Android BLE 使用的藍(lán)牙協(xié)議是 GATT 協(xié)議,,有關(guān)該協(xié)議的詳細(xì)內(nèi)容可以參見官方文檔

Service

一個低功耗藍(lán)牙設(shè)備可以定義許多 Service, Service 可以理解為一個功能的集合,。設(shè)備中每一個不同的 Service 都有一個 128 bit 的 UUID 作為這個 Service 的獨(dú)立標(biāo)志,。藍(lán)牙核心規(guī)范制定了兩種不同的UUID,一種是基本的UUID,,一種是代替基本UUID的16位UUID,。所有的藍(lán)牙技術(shù)聯(lián)盟定義UUID共用了一個基本的UUID: 0x0000xxxx-0000-1000-8000-00805F9B34FB 為了進(jìn)一步簡化基本UUID,每一個藍(lán)牙技術(shù)聯(lián)盟定義的屬性有一個唯一的16位UUID,,以代替上面的基本UUID的'x’部分,。例如,心率測量特性使用0X2A37作為它的16位UUID,,因此它完整的128位UUID為: 0x00002A37-0000-1000-8000-00805F9B34FB

Characteristic

在 Service 下面,,又包括了許多的獨(dú)立數(shù)據(jù)項,,我們把這些獨(dú)立的數(shù)據(jù)項稱作 Characteristic。同樣的,,每一個 Characteristic 也有一個唯一的 UUID 作為標(biāo)識符,。在 Android 開發(fā)中,建立藍(lán)牙連接后,,我們說的通過藍(lán)牙發(fā)送數(shù)據(jù)給外圍設(shè)備就是往這些 Characteristic 中的 Value 字段寫入數(shù)據(jù),;外圍設(shè)備發(fā)送數(shù)據(jù)給手機(jī)就是監(jiān)聽這些 Charateristic 中的 Value 字段有沒有變化,如果發(fā)生了變化,,手機(jī)的 BLE API 就會收到一個監(jiān)聽的回調(diào),。

Android BLE API 簡介

BluetoothAdapter BluetoothAdapter 擁有基本的藍(lán)牙操作,例如開啟藍(lán)牙掃描,,使用已知的 MAC 地址 (BluetoothAdapter#getRemoteDevice)實(shí)例化一個 BluetoothDevice 用于連接藍(lán)牙設(shè)備的操作等等,。

BluetoothDevice 代表一個遠(yuǎn)程藍(lán)牙設(shè)備。這個類可以讓你連接所代表的藍(lán)牙設(shè)備或者獲取一些有關(guān)它的信息,,例如它的名字,,地址和綁定狀態(tài)等等。

BluetoothGatt 這個類提供了 Bluetooth GATT 的基本功能,。例如重新連接藍(lán)牙設(shè)備,,發(fā)現(xiàn)藍(lán)牙設(shè)備的 Service 等等。

BluetoothGattService 這一個類通過 BluetoothGatt#getService 獲得,,如果當(dāng)前服務(wù)不可見那么將返回一個 null,。這一個類對應(yīng)上面說過的 Service。我們可以通過這個類的 getCharacteristic(UUID uuid) 進(jìn)一步獲取 Characteristic 實(shí)現(xiàn)藍(lán)牙數(shù)據(jù)的雙向傳輸,。

BluetoothGattCharacteristic 這個類對應(yīng)上面提到的 Characteristic,。通過這個類定義需要往外圍設(shè)備寫入的數(shù)據(jù)和讀取外圍設(shè)備發(fā)送過來的數(shù)據(jù)。

二,、開始使用

1.聲明權(quán)限,,在AndroidManifest.xml里面聲明:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
在API21(Android5.0)之后還需要加:

<uses-feature android:name="android.hardware.location.gps" />
在Android6.0以后還需要加:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
好了,權(quán)限聲明完成就到了我們的代碼環(huán)節(jié)

2.初始化BluetoothAdapter

private BluetoothAdapter mAdapter;
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mAdapter = bluetoothManager.getAdapter();

3.如果藍(lán)牙沒有打開先打開藍(lán)牙

if (mAdapter == null || !mAdapter.isEnabled()) {
    // 彈對話框的形式提示用戶開啟藍(lán)牙
    //startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);  
   mBluetoothAdapter.enable();
}

4.掃描設(shè)備

掃描設(shè)備有兩種,,一種是過濾特別的服務(wù)掃描,,一種是全部掃描

下面代碼演示全部掃描

mAdapter.startLeScan(mLeScanCallback); // 開始掃描

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

   @Override
   public void onLeScan(final BluetoothDevice device, int rssi,
         byte[] scanRecord) {    
Log.i("掃描到",device.getName()+"rssi"+rssi);
}};停止掃描

mAdapter.stopLeScan(mLeScanCallback);   // 停止掃描

5.連接GATT服務(wù)端

連接藍(lán)牙設(shè)備可以通過 BluetoothDevice#ConnectGatt 方法連接,也可以通過 BluetoothGatt#connect 方法進(jìn)行重新連接,。以下分別是兩個方法的官方說明:

  1. BluetoothDevice#connectGatt
  2. BluetoothGatt connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)

第二個參數(shù)表示是否需要自動連接,。如果設(shè)置為 true, 表示如果設(shè)備斷開了,會不斷的嘗試自動連接,。設(shè)置為 false 表示只進(jìn)行一次連接嘗試,。

第三個參數(shù)是連接后進(jìn)行的一系列操作的回調(diào),例如連接和斷開連接的回調(diào),,發(fā)現(xiàn)服務(wù)的回調(diào),,成功寫入數(shù)據(jù),,成功讀取數(shù)據(jù)的回調(diào)等等。

BluetoothDevice device = mAdapter.getRemoteDevice(address);
device.connectGatt(this, false, mGattCallback);
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                        int newState) {
        
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        
       
    }



    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic, int status) {
       
          
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
       
    }
};
當(dāng)調(diào)用藍(lán)牙的連接方法之后,,藍(lán)牙會異步執(zhí)行藍(lán)牙連接的操作,,如果連接成功會回調(diào) BluetoothGattCalbackl#onConnectionStateChange 方法。這個方法運(yùn)行的線程是一個 Binder 線程,,所以不建議直接在這個線程處理耗時的任務(wù),,因為這可能導(dǎo)致藍(lán)牙相關(guān)的線程被阻塞。

這一個方法有三個參數(shù),,第一個就藍(lán)牙設(shè)備的 Gatt 服務(wù)連接類,。

第二個參數(shù)代表是否成功執(zhí)行了連接操作,如果為 BluetoothGatt.GATT_SUCCESS 表示成功執(zhí)行連接操作,,第三個參數(shù)才有效,,否則說明這次連接嘗試不成功。根據(jù)網(wǎng)上大部分人的說法,,這是因為 Android 最多支持連接 6 到 7 個左右的藍(lán)牙設(shè)備,,如果超出了這個數(shù)量就無法再連接了。所以當(dāng)我們斷開藍(lán)牙設(shè)備的連接時,,還必須調(diào)用 BluetoothGatt#close 方法釋放連接資源,。

第三個參數(shù)代表當(dāng)前設(shè)備的連接狀態(tài),如果 newState == BluetoothProfile.STATE_CONNECTED 說明設(shè)備已經(jīng)連接,,可以進(jìn)行下一步的操作了(發(fā)現(xiàn)藍(lán)牙服務(wù),,也就是 Service)。當(dāng)藍(lán)牙設(shè)備斷開連接時,,這一個方法也會被回調(diào),,其中的 newState == BluetoothProfile.STATE_DISCONNECTED。

6.發(fā)現(xiàn)服務(wù)

在成功連接到藍(lán)牙設(shè)備之后才能進(jìn)行這一個步驟,,調(diào)用 BluetoothGatt#discoverService 這一個方法,。當(dāng)這一個方法被調(diào)用之后,系統(tǒng)會異步執(zhí)行發(fā)現(xiàn)服務(wù)的過程,,直到 BluetoothGattCallback#onServicesDiscovered 被系統(tǒng)回調(diào)之后,,手機(jī)設(shè)備和藍(lán)牙設(shè)備才算是真正建立了可通信的連接。

if (newState == BluetoothProfile.STATE_CONNECTED) {
    mBluetoothGatt.discoverServices();
}

7.讀寫設(shè)備

當(dāng)我們發(fā)現(xiàn)服務(wù)之后就可以通過 BluetoothGatt#getService 獲取 BluetoothGattService,,接著通過 BluetoothGattService#getCharactristic 獲取 BluetoothGattCharactristic。

通過 BluetoothGattCharactristic#readCharacteristic 方法可以通知系統(tǒng)去讀取特定的數(shù)據(jù),。如果系統(tǒng)讀取到了藍(lán)牙設(shè)備發(fā)送過來的數(shù)據(jù)就會調(diào)用 BluetoothGattCallback#onCharacteristicRead 方法,。

通過 BluetoothGattCharacteristic#getValue 可以讀取到藍(lán)牙設(shè)備的數(shù)據(jù)。

// 讀取數(shù)據(jù)
BluetoothGattService service = mBluetoothGatt.getService("需要讀取的服務(wù)");
BluetoothGattCharacteristic characteristic = service.getCharacteristic("需要讀取的特征");
mBluetoothGatt.readCharacteristic(characteristic);
/**
 * BLE終端數(shù)據(jù)被讀的事件
 */
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
                                 BluetoothGattCharacteristic characteristic, int status) {

    Log.i("onCharacteristicRead","讀取的回調(diào)"+characteristic.getValue());


}

和讀取數(shù)據(jù)一樣,,在執(zhí)行寫入數(shù)據(jù)前需要獲取到 BluetoothGattCharactristic,。接著執(zhí)行一下步驟:

  1. 調(diào)用 BluetoothGattCharactristic#setValue 傳入需要寫入的數(shù)據(jù)(藍(lán)牙最多單次1支持 20 個字節(jié)數(shù)據(jù)的傳輸,,如果需要傳輸?shù)臄?shù)據(jù)大于這一個字節(jié)則需要分包傳輸)。
  2. 調(diào)用 BluetoothGattCharactristic#writeCharacteristic 方法通知系統(tǒng)異步往設(shè)備寫入數(shù)據(jù),。
  3. 系統(tǒng)回調(diào) BluetoothGattCallback#onCharacteristicWrite 方法通知數(shù)據(jù)已經(jīng)完成寫入,。此時,我們需要執(zhí)行 BluetoothGattCharactristic#getValue 方法檢查一下寫入的數(shù)據(jù)是否我們需要發(fā)送的數(shù)據(jù),,如果不是按照項目的需要判斷是否需要重發(fā),。
BluetoothGattService service = mBluetoothGatt.getService("需要寫的服務(wù)");
BluetoothGattCharacteristic characteristic = service.getCharacteristic("需要寫的特征");
characteristic.setValue("需要寫入的數(shù)據(jù)");
mBluetoothGatt.writeCharacteristic(characteristic);
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    if(!characteristic.getValue().equals("需要寫入的數(shù)據(jù)")) {
        // 執(zhí)行重發(fā)策略
        gatt.writeCharacteristic(characteristic);
    }
}

通知

mBluetoothGatt.setCharacteristicNotification(characteristic, true);

BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
        UUID.fromString(""));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);//或者descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);

mBluetoothGatt.writeDescriptor(descriptor);
然后來的通知就會回調(diào)在

public void onCharacteristicChanged(BluetoothGatt gatt,
                                    BluetoothGattCharacteristic characteristic) {

}

8.斷開連接

當(dāng)我們連接藍(lán)牙設(shè)備完成一系列的藍(lán)牙操作之后就可以斷開藍(lán)牙設(shè)備的連接了。通過 BluetoothGatt#disconnect 可以斷開正在連接的藍(lán)牙設(shè)備,。當(dāng)這一個方法被調(diào)用之后,,系統(tǒng)會異步回調(diào) BluetoothGattCallback#onConnectionStateChange 方法。通過這個方法的 newState 參數(shù)可以判斷是連接成功還是斷開成功的回調(diào),。由于 Android 藍(lán)牙連接設(shè)備的資源有限,,當(dāng)我們執(zhí)行斷開藍(lán)牙操作之后必須執(zhí)行 BluetoothGatt#close 方法釋放資源。需要注意的是通過 BluetoothGatt#close 方法也可以執(zhí)行斷開藍(lán)牙的操作,,不過 BluetoothGattCallback#onConnectionStateChange 將不會收到任何回調(diào),。此時如果執(zhí)行 BluetoothGatt#connect 方法會得到一個藍(lán)牙 API 的空指針異常。所以,,我們推薦的寫法是當(dāng)藍(lán)牙成功連接之后,,通過 BluetoothGatt#disconnect 斷開藍(lán)牙的連接,緊接著在 BluetoothGattCallback#onConnectionStateChange 執(zhí)行 BluetoothGatt#close 方法釋放資源,。

@Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status,
                                    final int newState) {
    Log.d(TAG, "onConnectionStateChange: thread "
            + Thread.currentThread() + " status " + newState);

    if (status != BluetoothGatt.GATT_SUCCESS) {
        String err = "Cannot connect device with error status: " + status;
        // 當(dāng)嘗試連接失敗的時候調(diào)用 disconnect 方法是不會引起這個方法回調(diào)的,,所以這里
        //   直接回調(diào)就可以了。
        gatt.close();
        Log.e(TAG, err);
        return;
    }

    if (newState == BluetoothProfile.STATE_CONNECTED) {
        gatt.discoverService();
    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
        gatt.close();
    }
}

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多