我們在《Android藍牙開發系列文章-策劃篇》中計劃講解一下藍牙BLE,現在開始第一篇:Android藍牙開發系列文章-玩轉BLE開發(一)。計劃要寫的BLE文章至少分四篇,其他三篇分別講解:BLE Server端編碼(用手機模擬外圍設備),BLE Beacon功能,BLE設備通信(利用自有協議實現Client和Server端通信,在Server端信息改變時,自動上報給Client)。
本文主要內容:編碼實現BLE Client端,實現手機與藍牙體重秤之間的通信
所用的設備:華爲榮耀7手機,微信小程序,樂心體重秤
目錄
1.基本概念
在這裏先講解一下BLE(Bluetooth Low Energy)的一些簡單概念。
本文會涉及一個概念叫“GATT連接”,那我們先說一下什麼是GATT,GATT(GenericAttribute Profile)譯爲通用屬性配置文件。GATT連接利用的是在外設(體重秤)與中心設備(手機)之間建議一種聯繫,這種聯繫利用的是雙方之間都能夠識別(或者說提前約定好)的協議。這種協議的基礎就是GATT。
GATT由service、characteristic、descriptor元素組成。service是一個功能單元的集合,這個集合有SIG標準的,也可以自己定義的。一個service可以包含一個或者多個characteristic,每個characteristic包含一個value和一個或者多個descriptor。descriptor是對characteristic的描述,例如是否支持讀取等。
我們說的利用GATT通信就是對characteristic的讀、寫、或者characteristic的值發生改變時的自動上報(方向爲:從藍牙體重秤到手機)。
一個BLE設備往往支持多個service,即多個功能集合。例如,現在智能電視遙控器也許會支持藍牙電量的service、蜂鳴的service以及一些自定義的service。
按照我個人的理解,畫了一個BLE設備的GATT的結構如下,僅供大家參考。
2.先來認識一下我們的設備
俗話說“知彼知己,百戰不殆”,我們在動手碼代碼前,要先來了解一下我們所用的設備,不然代碼寫了一半了,才意識到我們這個功能根本完成不了,那不是呵呵了。
我的測試手機是榮耀7,Android版本爲Android6,因爲BLE是從Android4.3開始支持的,所以我的手機應該可以過關了。
利用微信小程序“BLE藍牙開發助手”可以搜索到家裏的體脂秤,並且可以建立連接。利用該小程序可以看到該款體重秤有4個service,點擊中某個service中的characteristic,可以正常讀取數據,說明手機與體重秤之間建立通信應該沒有問題。
下面我們要做的就是實現微信小程序類似的功能,與體重秤建立通信,並獲取數據。
3、認識BLE Client編碼
本文以《Android藍牙開發系列文章-掃不到藍牙設備,你的姿勢對了嗎?》中的代碼爲基礎,進行了添加和修改。
3.1 掃描BLE設備
利用微信小程序,我們可以知道體重秤支持UUID爲“0000FEE7-0000-1000-8000-00805F9B34FB”的service,所以,我在設備過濾條件裏指定了UUID,相關代碼如下:
private void startBleScan2() {
// mBluetoothLeScanner.startScan(mScanCallback);
//過濾條件
List<ScanFilter> bleScanFilters = new ArrayList<>();
// ScanFilter filter = new ScanFilter.Builder().setDeviceAddress("08:7C:BE:48:65:AD").setServiceUuid(ParcelUuid.fromString("0000fee7-0000-1000-8000-00805f9b34fb")).build();
ScanFilter filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("0000FEE7-0000-1000-8000-00805F9B34FB")).build();
bleScanFilters.add(filter);
//掃描設置
ScanSettings scanSetting = new ScanSettings.Builder().setScanMode(SCAN_MODE_LOW_LATENCY).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).setMatchMode(ScanSettings.MATCH_MODE_STICKY).build();
mBluetoothLeScanner.startScan(bleScanFilters, scanSetting, mScanCallback);
}
3.2 建立GATT連接
在掃描到目標設備後,我們將BluetoothDevice對象記錄下來。先停掉BLE掃描,然後發起GATT連接。
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
Log.d(TAG, "onScanResult, result = " + result);
Message msg = new Message();
msg.what = MSG_FIND_TARGET;
msg.obj = result.getDevice();
mHandler.sendMessage(msg);
}
};
mHandler = new Handler(){
@NonNull
@Override
public void dispatchMessage(Message msg) {
Log.d(TAG, "dispatchMessage, msg = " + msg.what);
switch (msg.what) {
case MSG_FIND_TARGET:
mTargetDevice = (BluetoothDevice) msg.obj;
stopBleScan2();
mBluetoothGatt = mTargetDevice.connectGatt(getApplicationContext(), false, mBluetoothGattCallback);
break;
}
}
};
GATT連接調用的是BluetoothDevice::connectGatt(Contextcontext,)方法,先說一下參數的含義。
autoConnect表示是否接着發起gatt連接,若值爲false,則表示立即發起連接,若值爲true,則表示爲等到設備變爲available時再發起連接。因爲我們這裏是掃描到設備後發起連接的,所以直接傳入false就OK了。
callback是用於獲取連接狀態改變的回調,該回調是本文的重點,下面詳細講一下。
/**
* Connect to GATT Server hosted by this device. Caller acts as GATT client.
* The callback is used to deliver results to Caller, such as connection status as well
* as any further GATT client operations.
* The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
* GATT client operations.
*
* @param callback GATT callback handler that will receive asynchronous callbacks.
* @param autoConnect Whether to directly connect to the remote device (false) or to
* automatically connect as soon as the remote device becomes available (true).
* @throws IllegalArgumentException if callback is null
*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback) {
return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO));
}
我摘取了部分BluetoothGattCallback中的方法,進行簡單的解釋:
/**
* This abstract class is used to implement {@link BluetoothGatt} callbacks.
*/
public abstract class BluetoothGattCallback {
//連接狀態改變的回調,status爲BluetoothGatt#GATT_SUCCESS表示連接成功,
//newState表示連接狀態改變後的值,可能值爲BluetoothProfile#STATE_DISCONNECTED
//或者爲BluetoothProfile#STATE_CONNECTED
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
}
//調用了BluetoothGatt:: discoverServices()方法的回調
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
}
//調用了BluetoothGatt::readCharacteristic()方法的回調,在status值爲//BluetoothGatt#GATT_SUCCESS時表示我們想要的值讀取成功了
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
}
//調用了BluetoothGatt::writeCharacteristic()方法的回調,在status值爲
//BluetoothGatt#GATT_SUCCESS時表示我們對characteristic執行寫操作成功了
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
}
//在server端的某個characteristic改變時會回調到這裏,當然,前提是設置了//notification
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
}
//在執行了讀取descriptor的回調,同樣,status值表徵了操作是否成功
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
}
//在執行了修改descriptor的回調,status值爲BluetoothGatt#GATT_SUCCESS表示修改成了
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
}
}
3.3 解析設備支持的characteristic
在onConnectionStateChange()回調中,如果status爲BluetoothGatt.GATT_SUCCESS且newState爲BluetoothProfile.STATE_CONNECTED,則可以發起service掃描,即獲取體重秤所支持的service。
如果newState不爲BluetoothProfile.STATE_CONNECTED,則釋放gatt連接資源,並重新發起連接。
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.d(TAG, "onConnectionStateChange, status = " + status + ", newState = " + newState);
if (status == BluetoothGatt.GATT_SUCCESS) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mBluetoothGatt.discoverServices();
} else {
mBluetoothGatt.close();
mBluetoothGatt = mTargetDevice.connectGatt(getApplicationContext(), false, mBluetoothGattCallback);
}
}
}
在搜索完成體重秤的service後,應用層會收到onServiceDiscovered()回調。我們按照service->characteristic->descriptor層次結構,進行解析。
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.d(TAG, "onServicesDiscovered, status = " + status);
List<BluetoothGattService> gattServicesList = mBluetoothGatt.getServices();
parseService(gattServicesList);
}
private void parseService(List<BluetoothGattService> gattServiceList) {
Log.d(TAG, "----- start parseServie -----");
for (int i = 0; i < gattServiceList.size(); i++) {
BluetoothGattService gattService = (BluetoothGattService)gattServiceList.get(i);
UUID uuid = gattService.getUuid();
Log.d(TAG, "parseService, service uuid = " + uuid);
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
for (int j = 0; j < gattCharacteristics.size(); j++) {
BluetoothGattCharacteristic gattCharacteristic = gattCharacteristics.get(j);
int properties = gattCharacteristic.getProperties();
int permission = gattCharacteristic.getPermissions();
Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " properties = " + properties);
if (0 != (properties & BluetoothGattCharacteristic.PROPERTY_READ)) {
Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support read");
if (gattCharacteristic.getUuid().toString().equals(LeXinUUID.READ_CHARA)) {
Message msg = new Message();
msg.what = MSG_READ_CHARA;
msg.obj = gattCharacteristic;
mHandler.sendMessageDelayed(msg, DELAY_TIMES);
}
// mBluetoothGatt.readCharacteristic(gattCharacteristic);
}
if ((0 != (properties & BluetoothGattCharacteristic.PROPERTY_INDICATE))) {
Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support indicate");
if (gattCharacteristic.getUuid().toString().equals(LeXinUUID.INDICATE_CHARA)) {
Message msg = new Message();
msg.what = MSG_INDICATE;
msg.obj = gattCharacteristic;
mHandler.sendMessageDelayed(msg, 3*DELAY_TIMES);
}
}
if (0 != (properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY)) {
Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support notify");
}
if ((0 != (properties & BluetoothGattCharacteristic.PROPERTY_WRITE))) {
Log.d(TAG, "gattCharacteristic, characteristic uuid = " + gattCharacteristic.getUuid() + " support write");
if (gattCharacteristic.getUuid().toString().equals(LeXinUUID.WRITE_CHARA)) {
Message msg = new Message();
msg.what = MSG_WRITE_CHARA;
msg.obj = gattCharacteristic;
mHandler.sendMessageDelayed(msg, 2*DELAY_TIMES);
}
}
List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();
for (int k = 0; k < gattDescriptors.size(); k++) {
BluetoothGattDescriptor gattDescriptor = (BluetoothGattDescriptor)gattDescriptors.get(k);
Log.d(TAG, "gattDescriptors, descriptor uuid = " + gattDescriptor.getUuid());
// gattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
// mBluetoothGatt.writeDescriptor(gattDescriptor);
}
}
}
Log.d(TAG, "----- parseServie end -----");
}
在解析的過程中,我們判斷了characteristic的properties是否支持read、write、notify、indicate。解析結果如下:
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: ----- start parseServie -----
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 00001800-0000-1000-8000-00805f9b34fb
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a00-0000-1000-8000-00805f9b34fb properties = 10
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a00-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a00-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a01-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a01-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a02-0000-1000-8000-00805f9b34fb properties = 10
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a02-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a02-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a04-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a04-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a03-0000-1000-8000-00805f9b34fb properties = 14
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a03-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a03-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 00001801-0000-1000-8000-00805f9b34fb
03-22 21:39:10.794 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a05-0000-1000-8000-00805f9b34fb properties = 34
03-22 21:39:10.795 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a05-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.795 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a05-0000-1000-8000-00805f9b34fb support indicate
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 0000fee7-0000-1000-8000-00805f9b34fb
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec8-0000-1000-8000-00805f9b34fb properties = 32
03-22 21:39:10.797 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec8-0000-1000-8000-00805f9b34fb support indicate
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec9-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec9-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec7-0000-1000-8000-00805f9b34fb properties = 8
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 0000fec7-0000-1000-8000-00805f9b34fb support write
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 0000180a-0000-1000-8000-00805f9b34fb
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a29-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a29-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a24-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a24-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a25-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a25-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a27-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a27-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a26-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a26-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a28-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a28-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a23-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a23-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a2a-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a2a-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a50-0000-1000-8000-00805f9b34fb properties = 2
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 00002a50-0000-1000-8000-00805f9b34fb support read
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = 0000fee8-0000-1000-8000-00805f9b34fb
03-22 21:39:10.799 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 003784cf-f7e3-55b4-6c4c-9fd140100a16 properties = 16
03-22 21:39:10.800 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 003784cf-f7e3-55b4-6c4c-9fd140100a16 support notify
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002901-0000-1000-8000-00805f9b34fb
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = 013784cf-f7e3-55b4-6c4c-9fd140100a16 properties = 4
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: parseService, service uuid = d618d000-6000-1000-8000-000000000000
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d002-6000-1000-8000-000000000000 properties = 32
03-22 21:39:10.801 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d002-6000-1000-8000-000000000000 support indicate
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: gattDescriptors, descriptor uuid = 00002902-0000-1000-8000-00805f9b34fb
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d001-6000-1000-8000-000000000000 properties = 8
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: gattCharacteristic, characteristic uuid = d618d001-6000-1000-8000-000000000000 support write
03-22 21:39:10.803 5392-5429/com.atlas.devicefinder D/MainActivity: ----- parseServie end -----
3.4 讀取characteristic值
我們根據上面的解析結果,選取了00002a50-0000-1000-8000-00805f9b34fb來做實驗,在解析到該characteristic時,我們讀取該屬性值,代碼看3.2部分代碼塊。在回調onCharacteristicRead()中添加如下的打印,
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status) {
super.onCharacteristicRead(gatt, characteristic, status);
Log.d(TAG, "onCharacteristicRead, characteristic = " + characteristic + ", status = " + status + ", value = " + characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0));
}
實驗結果如下,說明我們收到了相應的回調,因爲我們沒有獲取實際的協議,不知道這個值表示的實際含義。
03-24 21:13:09.645 20927-20938/com.atlas.devicefinder D/MainActivity: onCharacteristicRead, characteristic = android.bluetooth.BluetoothGattCharacteristic@2ac9086, status = 0, value = 1027
3.5 寫characteristic值
我們選取了"0000fec7-0000-1000-8000-00805f9b34fb"characteristic,在解析到該characteristic時,去讀取該屬性值。部分代碼請查看3.2部分的代碼段。
mHandler = new Handler(){
@NonNull
@Override
public void dispatchMessage(Message msg) {
Log.d(TAG, "dispatchMessage, msg = " + msg.what);
switch (msg.what) {
case MSG_WRITE_CHARA:
BluetoothGattCharacteristic gattCharacteristic2 = (BluetoothGattCharacteristic) msg.obj;
gattCharacteristic2.setValue("0");
mBluetoothGatt.writeCharacteristic(gattCharacteristic2);
break;
}
}
};
在回調onCharacteristicWrite()中添加如下的打印,
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.d(TAG, "onCharacteristicWrite, characteristic = " + characteristic + ", value = " + characteristic.getStringValue(0) + ", status = " + status);
}
實驗結果如下,說明我們成功修改了該屬性的值。
03-24 21:32:15.318 25167-25167/com.atlas.devicefinder D/MainActivity: dispatchMessage, msg = 2
03-24 21:32:15.385 25167-25366/com.atlas.devicefinder D/MainActivity: onCharacteristicWrite, characteristic = android.bluetooth.BluetoothGattCharacteristic@78102ba, value = 0, status = 0
3.6 設置indication
我們選取了"d618d002-6000-1000-8000-000000000000"characteristic,其持有的descripotor UUID爲"00002902-0000-1000-8000-00805f9b34fb"。
設置方法如下:
mHandler = new Handler(){
@NonNull
@Override
public void dispatchMessage(Message msg) {
Log.d(TAG, "dispatchMessage, msg = " + msg.what);
switch (msg.what) {
case MSG_INDICATE:
BluetoothGattCharacteristic gattCharacteristic3 = (BluetoothGattCharacteristic) msg.obj;
boolean ret =mBluetoothGatt.setCharacteristicNotification(gattCharacteristic3, true);
BluetoothGattDescriptor descriptor = gattCharacteristic3.getDescriptor(UUID.fromString(LeXinUUID.INDICATE_DES));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
break;
}
}
};
在onCharacteristicChanged ()和onDescriptorWrite()中添加如下打印。
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
Log.d(TAG, "onCharacteristicChanged, characteristic = " + characteristic + ", value = " + characteristic.getValue());
}
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
super.onDescriptorWrite(gatt, descriptor, status);
Log.d(TAG, "onDescriptorWrite, descriptor = " + descriptor + ", status = " + status);
}
實際運行結果如下,僅有onDescriptorWrite()的打印,沒有onCharateristicChanged()的打印,可能是因爲我沒有觸發到該屬性值發起改變的緣故(多次嘗試體重測量都沒有回調)。
設置notification的方法跟設置indication類似,只需要對對應的descriptor設置BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE。
綜上,就是BLE Client端編程主要內容。
4、總結
本文重點是開篇的BLE設備的結構,即characteristic是以service爲基礎的,descriptor是以characteristic爲基礎的,我們修改某個characteristic時,先要確定好service是那個。
如果想持續關注本博客內容,請掃描關注個人微信公衆號,或者微信搜索:萬物互聯技術。