最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android?藍(lán)牙BLE開發(fā)完全指南

 更新時間:2021年11月24日 10:36:12   作者:RalfNick  
BLE藍(lán)牙的興起主要因為近年來可穿戴設(shè)備的流行,由于傳統(tǒng)藍(lán)牙功耗高不能滿足可穿戴設(shè)備對于續(xù)航的要求,所以大部分可穿戴設(shè)備采用藍(lán)牙4.0,即BLE藍(lán)牙技術(shù),這篇文章主要給大家介紹了關(guān)于Android?藍(lán)牙BLE開發(fā)的相關(guān)資料,需要的朋友可以參考下

?介紹

1.BLE 是 Bluetooth Low Energy 的縮寫,意思為低功耗藍(lán)牙。由藍(lán)牙技術(shù)聯(lián)盟(Bluetooth SIG)設(shè)計的無線通訊技術(shù),主要用于醫(yī)療,健身,安全和家庭娛樂行業(yè)。 與傳統(tǒng)藍(lán)牙相比,藍(lán)牙低功耗旨在大幅降低功耗和成本,同時也能夠達(dá)到相同的通訊效果。

支持多個平臺,包括 IOS,Android,Windows Phone 和 BlackBerry 以及 macOS,Linux,Windows 8 和 Windows 10 在內(nèi)的移動操作系統(tǒng)本身支持藍(lán)牙低功耗。 藍(lán)牙 SIG 預(yù)測,到 2018 年,超過 90% 的藍(lán)牙智能手機將支持藍(lán)牙低功耗。

在安卓平臺,

在 Android 4.3 (API level 18) 以后引進(jìn)來的,通過這些 API 可以掃描藍(lán)牙設(shè)備、連接設(shè)備,查詢 services、讀寫設(shè)備的 characteristics(屬性特征),然后通過屬性進(jìn)行數(shù)據(jù)傳輸。

特點:

低功耗,使用 BLE 與周圍設(shè)備進(jìn)行通訊時,其峰值功耗為傳統(tǒng)藍(lán)牙的一半

傳輸距離提升到 100 米

低延時,最短可在3 ms內(nèi)完成連接并開始進(jìn)行數(shù)據(jù)傳輸

缺點:

傳輸數(shù)據(jù)量較小,最大 512 個字節(jié),超過 20 個字節(jié)需要分包處理

應(yīng)用領(lǐng)域:

主要用于智能硬件,像健康護(hù)理、運動和健身、設(shè)備電源管理等

連接模式

對于BLE單設(shè)備來講常見的藍(lán)牙模塊的工作模有四種:

主設(shè)備模式

從設(shè)備模式

廣播模式

Mesh組網(wǎng)模式

主設(shè)備模式

可以與一個從設(shè)備進(jìn)行連接。在此模式下可以對周圍設(shè)備進(jìn)行搜索并選擇需要連接的從設(shè)備進(jìn)行連接。同時可以設(shè)置默認(rèn)連接從設(shè)備的MAC地址,這樣模塊上電之后就可以查找此模塊并進(jìn)行連接。

從設(shè)備模式

BLE支持從設(shè)備模式,在此模式下完全符合BLE4.1協(xié)議,用戶可以根據(jù)協(xié)議自己開發(fā)APP。此模式下包含一個串口收發(fā)的Service,用戶可以通過UUID找到它,里面有兩個通道,分別是讀和寫。用戶可以操作這兩個通道進(jìn)行數(shù)據(jù)的傳輸。

廣播模式

在這種模式下模塊可以一對多進(jìn)行廣播。用戶可以通過AT指令設(shè)置模塊廣播的數(shù)據(jù),模塊可以在低功耗的模式下持續(xù)的進(jìn)行廣播,應(yīng)用于極低功耗,小數(shù)據(jù)量,單向傳輸?shù)膽?yīng)用場合,比如無線抄表,室內(nèi)定位等功能。

Mesh組網(wǎng)模式

在這種模式下模塊可以實現(xiàn)簡單的自組網(wǎng)絡(luò),每個模塊只需要設(shè)置相同的通訊密碼就可以加入到同一網(wǎng)絡(luò)當(dāng)中,每一個模塊都可以發(fā)起數(shù)據(jù),每個模塊可以收到數(shù)據(jù)并且進(jìn)行回復(fù)。并且不需要網(wǎng)關(guān),即使某一個設(shè)備出現(xiàn)故障也會跳過并選擇最近的設(shè)備進(jìn)行傳輸。

GATT協(xié)議

GATT generic Attributes的縮寫,中文是通用屬性,是低功耗藍(lán)牙設(shè)備之間進(jìn)行通信的協(xié)議。

GATT定義了一種多層的數(shù)據(jù)結(jié)構(gòu),已連接的低功耗藍(lán)牙設(shè)備用它來進(jìn)行通信,GATT層是傳輸真正數(shù)據(jù)所在的層。一個GATT服務(wù)器通過一個稱為屬性表的表格組織數(shù)據(jù),這些數(shù)據(jù)就是用于真正發(fā)送的數(shù)據(jù)。

GATT定義的多層數(shù)據(jù)結(jié)構(gòu)簡要概括起來就是服務(wù)(service)可以包含多個特征(characteristic),每個特征包含屬性(properties)和值(value),還可以包含多個描述(descriptor)。它形象的結(jié)構(gòu)如下圖:

profile(數(shù)據(jù)配置文件)

一個profile文件可以包含一個或者多個服務(wù),一個profile文件包含需要的服務(wù)的信息或者為對等設(shè)備如何交互的配置文件的選項信息。設(shè)備的GAP和GATT的角色都可能在數(shù)據(jù)的交換過程中改變,因此,這個文件應(yīng)該包含廣播的種類、所使用的連接間隔、所需的安全等級等信息。

需要注意的是: 一個profile中的屬性表不能包含另一個屬性表。

屬性

一個屬性包含句柄、UUID(類型)、值,句柄是屬性在GATT表中的索引,在一個設(shè)備中每一個屬性的句柄都是唯一的。UUID包含屬性表中數(shù)據(jù)類型的信息,它是理解屬性表中的值的每一個字節(jié)的意義的關(guān)鍵信息。在一個GATT表中可能有許多屬性,這些屬性能可能有相同的UUID。

個人理解,屬性指的是 Service、Characteristic 這樣的對象

Service

一個低功耗藍(lán)牙設(shè)備可以定義許多 Service, Service 可以理解為一個功能的集合。設(shè)備中每一個不同的 Service 都有一個 128 bit 的 UUID 作為這個 Service 的獨立標(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 下面,又包括了許多的獨立數(shù)據(jù)項,我們把這些獨立的數(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ù)給手機就是監(jiān)聽這些 Charateristic 中的 Value 字段有沒有變化,如果發(fā)生了變化,手機的 BLE API 就會收到一個監(jiān)聽的回調(diào)。

DesCriptor

任何在特性中的屬性不是定義為屬性值就是為描述符。描述符是一個額外的屬性以提供更多特性的信息,它提供一個人類可識別的特性描述的實例。然而,有一個特別的描述符值得特別地提起:客戶端特性配置描述符(Client Characteristic Configuration Descriptor,CCCD),這個描述符是給任何支持通知或指示功能的特性額外增加的。在CCCD中寫入“1”使能通知功能,寫入“2”使能指示功能,寫入“0”同時禁止通知和指示功能。

使用過程

常采用的模式是主機模式,然后掃描客戶端硬件,然后連接,獲取相關(guān)服務(wù)和特性,然后進(jìn)行數(shù)據(jù)傳輸。

掃描

權(quán)限獲取

<uses-permission android:name="android.permission.BLUETOOTH"/> 使用藍(lán)牙所需要的權(quán)限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 使用掃描和設(shè)置藍(lán)牙的權(quán)限(申明這一個權(quán)限必須申明上面一個權(quán)限)

在Android5.0之前,是默認(rèn)申請GPS硬件功能的。而在Android 5.0 之后,需要在manifest 中申明GPS硬件模塊功能的使用。

    <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
    <uses-feature android:name="android.hardware.location.gps" />

在 Android 6.0 及以上,還需要打開位置權(quán)限。如果應(yīng)用沒有位置權(quán)限,藍(lán)牙掃描功能不能使用(其它藍(lán)牙操作例如連接藍(lán)牙設(shè)備和寫入數(shù)據(jù)不受影響)。

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

除了上面的設(shè)置之外,如果想設(shè)置設(shè)備只支持 BLE,可以加上下面這句話

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

同樣,如果不想添加 BLE 的支持,那么可以設(shè)置 required="false"

然后可以在運行時判斷設(shè)備是否支持 BLE,

    // Use this check to determine whether BLE is supported on the device. Then
    // you can selectively disable BLE-related features.
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
        finish();
    }

初始化

判斷 BLE 在設(shè)備上是否支持,如果不支持的話,那么可以不用繼續(xù)后面的操作了;如果支持,但是有可能藍(lán)牙被禁掉了,因為開著藍(lán)牙比較好點,用戶一般都會關(guān)閉藍(lán)牙,這時候可以發(fā)送請求,來打開藍(lán)牙,可以通過兩個步驟來完成。

1.獲取 BluetoothAdapter

BluetoothAdapter 對于一個設(shè)備來說唯一的,整個系統(tǒng)或者應(yīng)用,對藍(lán)牙進(jìn)行操作時都是需要這個的適配器。它的獲取需要通過系統(tǒng)服務(wù)來獲取。

    private BluetoothAdapter mBluetoothAdapter;
    ...
    // Initializes Bluetooth adapter.
    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();

2.打開藍(lán)牙

一般對于用戶來說,在手機上藍(lán)牙是關(guān)閉,當(dāng)開啟你的應(yīng)用時就需要開啟藍(lán)牙,有兩種方式,一種是跳轉(zhuǎn)到設(shè)置界面,由用戶自己開啟藍(lán)牙;

另外一種時,直接在應(yīng)用開啟藍(lán)牙,不需要用戶打開,而是直接幫用戶開啟手機上的藍(lán)牙。

跳轉(zhuǎn)到設(shè)置界面

// Ensures Bluetooth is available on the device and it is enabled. If not,
// displays a dialog requesting user permission to enable Bluetooth.
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

直接開啟藍(lán)牙

    // 打開藍(lán)牙
    if (!mBluetoothAdapter.isEnabled()) {
        mBluetoothAdapter.enable();
    }

掃描

掃描藍(lán)牙設(shè)備可以通過startLeScan(),其中有一個參數(shù)是 ScanCallback,通過它返回掃描結(jié)果,因為掃描過程是很耗電的,所以在掃描過程需要保證

1.一旦找到目標(biāo)設(shè)備,需要停止掃描

2.掃描不要設(shè)置循環(huán),而且需要設(shè)置一個時間

回調(diào)如下

// 設(shè)備掃描回調(diào)
    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, final ScanResult result) {

            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                    // 廣播的信息,可以在result中獲取
                    MDevice mDev = new MDevice(result.getDevice(), result.getRssi());
                    if (!mList.contains(mDev)) {
                        mList.add(mDev);
                    }
                    if (mList.size() > 0) {
                        mScanner.stopScan(mScanCallback);
                        Toast.makeText(MainActivity.this, "掃描結(jié)束,設(shè)備數(shù) " + mList.size()
                                , Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    };

開始掃描

private BluetoothAdapter mBluetoothAdapter;
    private boolean mScanning;
    private Handler mHandler;

    // Stops scanning after 10 seconds.
    private static final long SCAN_PERIOD = 10000;
    ...
    private void scanLeDevice(final boolean enable) {
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                }
            }, SCAN_PERIOD);

            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
        ...
    }

這里遇到一個坑,就是實際中手機與一些智能硬件連接時,也就是需要連接指定的硬件,設(shè)備有一個UUID,所以可以通過如下方法連接

    startLeScan(UUID[], BluetoothAdapter.LeScanCallback)

但是實際中使用時,連接時會出錯,仍需要再次驗證。

我當(dāng)時的做法是采用了另外一種方法,當(dāng)時這種方法,要求 API 高于 21。

    private void scanLeDevice() {

        //50秒后停止掃描
        mHander.postDelayed(stopScanRunnable, 50000);

        List<ScanFilter> filters = new ArrayList<>();
        ScanFilter filter = new ScanFilter.Builder()
                //"D8:B0:4C:E8:66:DC" 測試MAC 1
                //"D8:B0:4C:E2:45:2A"  測試MAC 2
                .setDeviceAddress("D8:B0:4C:E2:45:2A")
                .build();
        filters.add(filter);

        // 掃描
        mScanner.startScan(filters, new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(), mScanCallback);

    }

掃描結(jié)束后需要停止掃描

boolean startLeScan(BluetoothAdapter.LeScanCallback callback)

連接

設(shè)備連接

通過掃描能夠獲得設(shè)備 BluetoothDevice,包含地址和名字

通過設(shè)備連接并獲取 BluetoothGatt,后面通過 BluetoothGatt 的實例來進(jìn)行client的操作,如使用該實例去發(fā)現(xiàn)服務(wù),獲取讀、寫、通知等屬性

public static BluetoothGatt mBluetoothGatt;

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

通過連接回調(diào)來監(jiān)聽連接的狀態(tài),包含三種狀態(tài),連接、斷開、正在連接,根據(jù)狀態(tài)可以發(fā)送廣播,

在接收廣播的位置進(jìn)行做相應(yīng)的處理

    private final static BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                            int newState) {

            String intentAction;
            // GATT Server connected
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                System.out.println("---------------------------->已經(jīng)連接");
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastConnectionUpdate(intentAction);
            }
            // GATT Server disconnected
            else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                System.out.println("---------------------------->連接斷開");
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                broadcastConnectionUpdate(intentAction);

            }
            // GATT Server disconnected
            else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                System.out.println("---------------------------->正在連接");
//                intentAction = ACTION_GATT_DISCONNECTING;
//                mConnectionState = STATE_DISCONNECTING;
//                broadcastConnectionUpdate(intentAction);
            }
        }
    }

當(dāng)操作完成后,需要關(guān)閉連接,必須調(diào)用 BluetoothGatt#close 方法釋放連接資源

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

由于有了 mBluetoothGatt,就可以去發(fā)現(xiàn)服務(wù),再通過服務(wù)去獲取可以操作的屬性

mBluetoothGatt.discoverServices();

發(fā)現(xiàn)服務(wù)以及獲取其他屬性,如write和read,notify,Descriptor相關(guān)的屬性,均是在 BluetoothGattCallback 中有回調(diào),在回調(diào)中就可以通過發(fā)送廣播,然后在其他位置做處理,

如接收數(shù)據(jù)就會有回調(diào),然后將數(shù)據(jù)傳遞出去,對數(shù)據(jù)解析等

 @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            // GATT Services discovered
            //發(fā)現(xiàn)新的服務(wù)
            if (status == BluetoothGatt.GATT_SUCCESS) {
                System.out.println("---------------------------->發(fā)現(xiàn)服務(wù)");
                broadcastConnectionUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            } 
        }

        //通過 Descriptor 寫監(jiān)聽
        @Override 
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
                                      int status) {

        }

        // 通過 Descriptor 讀監(jiān)聽
        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
                                     int status) {

        }


        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic
                characteristic, int status) {
            //write操作會調(diào)用此方法
            if (status == BluetoothGatt.GATT_SUCCESS) {
                System.out.println("onCharacteristicWrite ------------------->write success");
                Intent intent = new Intent(ACTION_GATT_CHARACTERISTIC_WRITE_SUCCESS);
                mContext.sendBroadcast(intent);
            } else {
                Intent intent = new Intent(ACTION_GATT_CHARACTERISTIC_ERROR);
                intent.putExtra(Constants.EXTRA_CHARACTERISTIC_ERROR_MESSAGE, "" + status);
                mContext.sendBroadcast(intent);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic, int status) {
            // 接收數(shù)據(jù)
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

            //notify 會回調(diào)用此方法
            broadcastNotifyUpdate(characteristic);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
           super.onMtuChanged(gatt, mtu, status);

        }

數(shù)據(jù)傳輸

1、數(shù)據(jù)讀取

這里有兩個方法:

方法一: 一般數(shù)據(jù)讀取的話,想到的是用 read 屬性,所以需要獲取特定通道的 BluetoothGattCharactristic。

1)BluetoothGatt#getService 得到服務(wù)

2)BluetoothGattService#getCharactristic 獲取 BluetoothGattCharactristic,這里獲取的 BluetoothGattCharactristic 是有指定 UUID 的,也就是說不同的 Charactristic的 UUID 是不同的,讀和寫的通道不同,根據(jù)不同的操作,然后通過UUID獲取相應(yīng)的通道

3)BluetoothGattCharactristic#readCharacteristic 方法可以通知系統(tǒng)去讀取特定的數(shù)據(jù)

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

方法二:采用 notify 屬性,客戶端發(fā)送數(shù)據(jù),服務(wù)端監(jiān)聽屬性變化,然后根據(jù) 屬性的 UUID 判斷是否是 notify 的屬性,如果是的話,說確實是由遠(yuǎn)程設(shè)備發(fā)過來的數(shù)據(jù)。

1)BluetoothGatt#getService 得到服務(wù)

2)BluetoothGattService#getCharactristic 獲取 BluetoothGattCharactristic,這里的這個屬性是 notify 屬性

3)獲得屬性后需要進(jìn)行判斷設(shè)備是否支持notify操作,然后再設(shè)備打開notify通知

void prepareBroadcastDataNotify(
            BluetoothGattCharacteristic characteristic) {

        final int charaProp = characteristic.getProperties();

        Toast.makeText(this, " " + charaProp, Toast.LENGTH_SHORT).show();

        if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
            BluetoothLeService.setCharacteristicNotification(characteristic, true);
        }

    }

4) 設(shè)置屬性時,也要通知遠(yuǎn)程設(shè)備端也要開啟 notify 屬性

public static void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            return;
        }
        //通知遠(yuǎn)程端開啟 notify 
        if (characteristic.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG)) != null) {
            if (enabled == true) {
                BluetoothGattDescriptor descriptor = characteristic
                        .getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                mBluetoothGatt.writeDescriptor(descriptor);
            } else {
                BluetoothGattDescriptor descriptor = characteristic
                        .getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
                descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                mBluetoothGatt.writeDescriptor(descriptor);
            }
        }
        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    }

數(shù)據(jù)寫入

對于 BLE 方式的數(shù)據(jù)傳輸來說,數(shù)據(jù)的大小是有限制的,一次性最多可以傳輸512個字節(jié),這也是BLE小數(shù)據(jù)量傳輸?shù)奶攸c,另外,對于每次傳輸,也有限制,每個數(shù)據(jù)包大小不超過20個字節(jié),超過20個字節(jié)的話,需要分包處理。寫的步驟和讀取類似。

1)BluetoothGatt#getService 得到服務(wù)

2)BluetoothGattService#getCharactristic 獲取 BluetoothGattCharactristic,這里的這個屬性是 write 屬性

3)寫入字節(jié)數(shù)據(jù)

public static void writeCharacteristicGattDb(
            BluetoothGattCharacteristic characteristic, byte[] byteArray) {

        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            return;
        } else {
            byte[] valueByte = byteArray;
            characteristic.setValue(valueByte);
            mBluetoothGatt.writeCharacteristic(characteristic);
        }
    }

4)對于手機端,寫入數(shù)據(jù)后,遠(yuǎn)程端會接受,同時回調(diào)中也會能夠接收,也可以在回調(diào)中做一下數(shù)據(jù)判斷,看是否是自己發(fā)出的數(shù)據(jù)

 @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic
                characteristic, int status) {
            //write操作會調(diào)用此方法
            if (status == BluetoothGatt.GATT_SUCCESS) {
                System.out.println("onCharacteristicWrite ------------------->write success");
                Intent intent = new Intent(ACTION_GATT_CHARACTERISTIC_WRITE_SUCCESS);
                // 這里通過屬性能夠讀取你發(fā)送的數(shù)據(jù),可以對此數(shù)據(jù)進(jìn)行判斷
                characteristic.getValue();
                mContext.sendBroadcast(intent);
            } else {
                Intent intent = new Intent(ACTION_GATT_CHARACTERISTIC_ERROR);
                intent.putExtra(Constants.EXTRA_CHARACTERISTIC_ERROR_MESSAGE, "" + status);
                mContext.sendBroadcast(intent);
            }
        }

其他

一般在通訊過程中,需要有連接的心跳包,來檢測是否仍處于連接狀態(tài),可以通過設(shè)置定時器,主機端定時 write 數(shù)據(jù),客戶端定時 notify 數(shù)據(jù)

斷開連接

操作完成,需要斷開藍(lán)牙并釋放資源,通過 BluetoothGatt#disconnect 斷開連接,然后回調(diào)中會收到斷開的監(jiān)聽,可以根據(jù)狀態(tài)釋放資源。BluetoothGattCallback#onConnectionStateChange回調(diào)中通過這個方法的 newState 參數(shù)可以判斷是連接成功還是斷開成功的回調(diào),斷開成功的話,然后調(diào)用 BluetoothGatt#close 方法釋放資源

參考

官方文檔

Android 開發(fā)入門介紹

通用屬性配置文件(GATT)及其服務(wù),特性與屬性介紹

總結(jié)

到此這篇關(guān)于Android?藍(lán)牙BLE開發(fā)完全指南的文章就介紹到這了,更多相關(guān)Android?藍(lán)牙BLE開發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android線程中Handle的使用講解

    Android線程中Handle的使用講解

    今天小編就為大家分享一篇關(guān)于Android線程中Handle的使用講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Android中ActionBar和ToolBar添加返回箭頭的實例代碼

    Android中ActionBar和ToolBar添加返回箭頭的實例代碼

    這篇文章主要介紹了Android中ActionBar和ToolBar添加返回箭頭的實例代碼,需要的朋友可以參考下
    2017-09-09
  • Android Studio生成函數(shù)注釋的實現(xiàn)方法

    Android Studio生成函數(shù)注釋的實現(xiàn)方法

    這篇文章主要介紹了Android Studio生成函數(shù)注釋的實現(xiàn)方法的相關(guān)資料,希望通過本文大家能夠?qū)崿F(xiàn)這樣的功能,需要的朋友可以參考下
    2017-09-09
  • Android實現(xiàn)短信、微信、微博分享功能

    Android實現(xiàn)短信、微信、微博分享功能

    微信、微博分享功能大家都體驗過吧,非常方便我們的生活,下面通過本文給大家介紹Android實現(xiàn)短信、微信、微博分享功能,需要的朋友參考下吧
    2017-12-12
  • Android Studio和Gradle使用不同位置JDK的問題解決

    Android Studio和Gradle使用不同位置JDK的問題解決

    這篇文章主要介紹了Android Studio和Gradle使用不同位置JDK的問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Android通過startService實現(xiàn)文件批量下載

    Android通過startService實現(xiàn)文件批量下載

    這篇文章主要為大家詳細(xì)介紹了Android通過startService實現(xiàn)文件批量下載的示例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-12-12
  • Android?Gson基本用法學(xué)習(xí)

    Android?Gson基本用法學(xué)習(xí)

    這篇文章介紹了Android?Gson的基本用法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • Android viewpage實現(xiàn)禁止滑動的功能

    Android viewpage實現(xiàn)禁止滑動的功能

    這篇文章主要介紹了Android viewpage實現(xiàn)禁止滑動的功能的相關(guān)資料,這里附有實現(xiàn)的實例代碼,主要還是重新 ViewPage 這個類,需要的朋友可以參考下
    2016-11-11
  • 詳解Android平臺上讀寫NFC標(biāo)簽

    詳解Android平臺上讀寫NFC標(biāo)簽

    NFC,即Near Field Communication,近距離無線通訊技術(shù),是一種短距離的(通常<=4cm或更短)高頻(13.56M Hz)無線通信技術(shù),可以讓消費者簡單直觀地交換信息、訪問內(nèi)容與服務(wù)。
    2017-01-01
  • Android仿微信多人音視頻通話界面

    Android仿微信多人音視頻通話界面

    這篇文章主要為大家詳細(xì)介紹了Android仿微信多人音視頻通話界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07

最新評論

丹巴县| 崇文区| 焦作市| 万宁市| 景洪市| 平遥县| 定兴县| 赤峰市| 容城县| 太谷县| 红桥区| 恭城| 湘潭市| 东明县| 诸暨市| 清水河县| 肥城市| 醴陵市| 富锦市| 宁强县| 黄石市| 吉水县| 凤山市| 苍梧县| 高邮市| 措美县| 盱眙县| 开远市| 永丰县| 寻甸| 资兴市| 崇信县| 黄平县| 固阳县| 方城县| 华宁县| 滦南县| 宿松县| 万载县| 泌阳县| 蓬莱市|