蓝牙技术联盟在2010年6月30号公布了蓝牙4.0标准,4.0标准在蓝牙3.0+HS标准的基础上增加了对低功耗蓝牙(Bluetooth Low Energy, BLE)的支持。相比原有的普通蓝牙和高速蓝牙,BLE最大的特点就是低功耗,低延时,快速的搜索和连接速度,但数据传输速度相比传统蓝牙低。

1. 数据发送

        本文将介绍BLE设备之间的数据传输,首先是数据的发送。数据的发送通过Characteristic完成,发送数据的Characteristic必须拥有写权限,即BluetoothGattCharacteristic类中的mProperties属性必须为以下两者中之一:

/**
     * 写权限:不需要响应
     */
    public static final int PROPERTY_WRITE_NO_RESPONSE = 0x04;

    /**
     * 写权限:需要响应
     */
    public static final int PROPERTY_WRITE = 0x08;

        在BLE的连接过程中,连接成功后会返回一个BluetoothGatt类型变量(见上一篇文章的2.7步骤),该类封装了BLE主要的操作。发送数据所需的Characteristic在BLE设备连接成功后的获取Service的过程中获得(见上一篇文章的2.10步骤),因此BLE的数据发送可以如下所示:


@Override
public boolean writeCharacteristic(ICharacteristicBle chrBle) {
	return mBleGatt.writeCharacteristic((BluetoothGattCharacteristic)chrBle);
}

        为了获取Characteristic的通知回调,在发送数据之前还需使能该Characteristic的通知:

/**
 * 设置characteristicde的通知
 * 
 * @param chrBle 设备的characteristic
 * @param enable 是否通知
 * @return 设置是否成功 
 */
 public boolean setCharacteristicNotification(ICharacteristicBle chrBle, boolean enable) {
 	return mBaseBle.setCharacteristicNotification(chrBle, enable);	
 }

        BLE的写入结果回调函数:

/**
 * 当写characteristics得到结果时回调
 * 如果该函数可信写入过程中被调用, 此时characteristics的返回值由设备决定. APP应当将该值与
 * 要求的值相比较, 如果两者不相等, 则APP将会终止可信写入过程.
 * 
 * @param bleGatt GATT客户端连接, 被{@link BluetoothGatt#writeCharacteristic}调用
 * @param bleChrc 写入相关设备的characteristics值
 * @param status 写入操作的结果, 如果写入成功时返回{@link BluetoothGatt#GATT_SUCCESS}
 */
 public void onCharacteristicWrite(BluetoothGatt bleGatt, BluetoothGattCharacteristic bleChrc, int status) {
			
 	/** 判断设备之间是否连接  */
 	if (status == BluetoothGatt.GATT_SUCCESS) {
								
		try {
			byte[] mByte = bleChrc.getValue();
			StringBuilder mStrBuilder = new StringBuilder(mByte.length);
						
			/** 逐byte转换 */
			for (byte mByteChar : mByte) {
					mStrBuilder.append(String.format("%02x", mByteChar));
				} /** end of for (byte mByteChar : mByte) */
						
				LogUtil.info(TAG, "device chrc write data: " + mStrBuilder.toString());
		} catch (Exception e) {
			LogUtil.error(TAG, "device chrc write data transform error");
			e.printStackTrace();
		}				
	} /** end of if (status == BluetoothGatt.GATT_SUCCESS) */ 

}

        在该回调函数中处理发送结果。

2. 数据接收

        数据接收的方式有2种:读取和通知。读取的方式速度较慢,但结果更稳定,通知的方式相反。在实际的使用过程中多用通知的方式。下面先介绍读取的方式,读取方式需要读取的Characteristic具有读取权限:

/**
 * 读权限
 */
public static final int PROPERTY_READ = 0x02;

        读取的函数:

@Override
public boolean readCharacteristic(ICharacteristicBle chrBle) {
	return mBleGatt.readCharacteristic((BluetoothGattCharacteristic)chrBle.getImpl());
}

        读取的结果在读取的回调函数获得:

/**
 * 当读取characteristics得到结果时回调
 * 
 * @param GATT客户端连接, 被{@link BluetoothGatt#readCharacteristic}调用
 * @param bleChrc 从相关设备读取的characteristics值
 * @param status 读取操作的结果, 如果读取操作成功时返回{@link BluetoothGatt#GATT_SUCCESS}
 */
public void onCharacteristicRead(BluetoothGatt bleGatt, BluetoothGattCharacteristic bleChrc, int status) {
			
	/** 判断设备之间是否连接  */
	if (status == BluetoothGatt.GATT_SUCCESS) {
		byte[] mByte = bleChrc.getValue();
		StringBuilder mStrBuilder = new StringBuilder(mByte.length);
					
		/** 逐byte转换 */
		for (byte mByteChar : mByte) {
			mStrBuilder.append(String.format("%02x", mByteChar));
		} /** end of for (byte mByteChar : mByte) */
				
		LogUtil.info(TAG, "device chrc change data: " + mStrBuilder.toString());
	} /** end of if (status == BluetoothGatt.GATT_SUCCESS) */
			
}

        接下来是通知的方式,其中通知方式的设置函数即是上文的通知函数,在设置成功之后,通过通知回调函数获取结果:

/**
 * 触发远程characteristics通知结果时回调
 * 
 * @param bleGatt 与characteristics相关联的GATT客户端连接
 * @param bleChrc 通知更新结果的characteristics
 */
 public void onCharacteristicChanged(BluetoothGatt bleGatt, BluetoothGattCharacteristic bleChrc) {			
	byte[] mByte = bleChrc.getValue();
	StringBuilder mStrBuilder = new StringBuilder(mByte.length);
	
	/** 逐byte转换 */
	for (byte mByteChar : mByte) {
		mStrBuilder.append(String.format("%02x", mByteChar));
	} /** end of for (byte mByteChar : mByte) */
			
	LogUtil.info(TAG, "device chrc change data: " + mStrBuilder.toString());					
}

        这样就完成了BLE的通信过程。


        附上两个BLE的Sample

        1.Google官方BLE用例

        https://github.com/googlesamples/android-BluetoothLeGatt

        2.一个希腊研究无线传感器网络(WSN)的博士写的BLE开源库

        https://github.com/alt236/Bluetooth-LE-Library---Android