赞
踩
最近穿戴设备发展得很火,我们公司也正在做健康类的穿戴设备,因此有机会研究了一把BLE(Bluetooth Low Energy)技术。
关于BLE技术的简介以及基本定义,本文就不再累述,各位看管可自行搜索查阅相关文档博客,本文只简述我个人对BLE开发过程的理解。
首先,关于BLE的通讯,是需要绑定在一个服务service上进行通讯的。因为BLE不像蓝牙2.0时代那样,维持一个长连接的BluetoothSocket,直接在这个Socket中通讯,通讯完成,关闭相关的Socket即可。而BLE之所以定义为低功耗的蓝牙,是因为它的通讯是每次有数据传输时才建立连接,传输完成连接就中断,因此才能做到低功耗。所以关于BLE的开发,才经常以开启一个service的形式来进行通讯。
// 将操作BLE的界面与服务绑定
mContext.bindService(new Intent(mContext,BluetoothLeService.class),mServiceConnection,Context.BIND_AUTO_CREATE);
// 服务绑定结果
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
// 处理服务绑定成功后的操作
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
isBound = true;
mHandler.sendEmptyMessage(ConstValue.DEVICE_SCAN_BIND_SERVICE);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
// 处理服务绑定结束后的操作
}
};
// 为了接收BLE的回调,注册广播接收器
mContext.registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
绑定了操作界面和BLE服务之后,就需要连接BLE设备了
// 通过BLE的蓝牙MAC地址进行连接
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) {
if (mBluetoothGatt.connect()) {
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
mBluetoothDeviceAddress = address;
return true;
}
其中,device.connectGatt(this, false, mGattCallback)的参数中,需要添加BLE的回调
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
broadcastUpdate(characteristic);
}
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
broadcastUpdate(characteristic);
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
broadcastUpdate(characteristic);
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
broadcastUpdate(characteristic);
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
Log.d("ble", "stefano105onReadRemoteRssi");
broadcastUpdate(characteristic);
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
broadcastUpdate(characteristic);
};
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.d("ble", "stefano107onCharacteristicChanged");
broadcastUpdate(characteristic);
}
};
关于上面的回调,很多大神也都有介绍使用方法(我觉得到了这个底部,BLE开发的公共部分该有的都有了,其他的就是依照不同的项目需求,来处理BLE的回调了)
最后,重点说明下开发过程中遇到的问题,以及个人理解和解决办法
* 设置多个Notify类型的特征值时,连续设置,会导致有些特征值并没有设置成功*
关于这个问题的详细技术原因,我也忘记了。。(主要是很久之前看到的,懒得再找了。。)反正大意就是,Android中的BLE设置命令并不是同步执行的,即不是执行完一个命令,再执行下一个命令。因为BLE执行设置命令是需要耗时的,所以如果连续的对BLE进行多个命令设置,会存在之前的命令还没有执行完,就被后一个命令覆盖,就导致上面的问题。
解决办法:因为设置命令,是需要write的,所以一个命令设置成功后,会回调以下函数
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {};
所以,对于需要连续设置多个命令的时候(如设置多个Notify类型的特征),虽然BLE无法将命令同步执行,但我们可以将设置命令先在本地代码中进行缓存,同步处理,如下
/**
***************************************************
* @ 功能描述: 设置多个监听特征值的方法
*/
public void setCharacteristicNotifications(Queue<BluetoothGattCharacteristic> characteristics, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
characteristicNotifyQueue = characteristics;
setCharacteristicNotification(characteristicNotifyQueue.element(), enabled);
}
当onDescriptorWrite回调成功时,再执行下一个命令的设置,直到所有的命令设置完成
if (status == BluetoothGatt.GATT_SUCCESS) {
characteristicNotifyQueue.remove();
if (characteristicNotifyQueue.size() > 0) {
setCharacteristicNotification(characteristicNotifyQueue.element(), true);
} else {
characteristicNotifyQueue.clear();
broadcastUpdate(UuidAndBroadcastFilter.ACTION_GATT_NOTIFYCATION_SETTED);
}
} else {
if (characteristicNotifyQueue.size() > 0) {
setCharacteristicNotification(characteristicNotifyQueue.element(), true);
}
}
这样,就解决这个问题!
以上是个人对于BLE开发的理解,不喜勿喷!!! 转载请说明出处~谢谢~~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。