Android 【蓝牙4.0 BLE 低功耗可穿戴设备】 开发总结

来源:互联网 发布:淘宝代刷灰烬套装 编辑:程序博客网 时间:2024/05/16 05:32

        最近在做可穿戴设备APP端的开发,之前没有相关知识的接触(android官方4.3版本才推出),在网上找了许久,资料也特别特别的少,无赖自己参考官方demo和文档。最终还是将设备连接成功,并且可以正常的收发数据命令。(花了我两个礼拜的时间呀!哭)以此进行总结,写下这篇博文。源代码就没有上传上来了,因为已经集成到项目APP中了,而这篇博文又是我后来写的。就只能贴上部分代码,希望对BLE刚接触的有少许帮助。

首先你要了解到蓝牙的基本概念及定义术语:

        请参考:http://www.blogjava.net/zh-weir/archive/2014/04/02/407373.html 【没有接触过BLE的请先看左边的链接

另外参考了:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=573261&highlight=BLE

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

本文地址:http://blog.csdn.net/yybj 转载请注明出处。

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        现在开始进入主题:

 一、先来介绍几个类 :

        BluetoothGatt,BluetoothGattService,BluetoothGattCharacteristic,BluetoothGattCallback  

        官方介绍网址是: https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html


       BluetoothGatt

         BluetoothGatt 是开发里最重要最常用到的东西了,我把它理解为手机与设备通信的管道。有了这个管道,收发数据就容易了。

           BluetoothGatt mBluetoothGatt = bluetoothDevice.connectGatt(this, false, mGattCallback);


这是官方的文档:

————————————————————————————————————————————————————————

public BluetoothGatt connectGatt (Context context, boolean autoConnect, BluetoothGattCallback callback)

Added in API level 18

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.

Parameters
autoConnectWhether to directly connect to the remote device (false) or to automatically connect as soon as the remote device becomes available (true).callbackGATT callback handler that will receive asynchronous callbacks.
Throws
IllegalArgumentExceptionif callback is null
————————————————————————————————————————————————————————
从这个文档我们可以看出   autoConnect  为false立刻发起一次连接;为true自动连接,只要蓝牙设备变得可用。

实测发现,用false连接比较好,比较快, true会等个十几秒甚至几分钟才会连接上。  开发过程中一般都是用false,扫描到bluetoothDevice之后,直接用false连接即可。BluetoothGattCallback   是非常重要的回调函数,手机与蓝牙设备的一切通信结果都在这里体现。待会细讲。


  BluetoothGattService

       蓝牙设备所拥有的服务。在这里比喻成【班级】吧。bluetoothDevice就比喻成【学校】吧。 一个学校可以有很多个班级。班级根据UUID来区别。(把这里的UUID当做班级的【班号】)


 

 BluetoothGattCharacteristic

 蓝牙设备所拥有的特征。比喻成【学生】。 一个班级里也可以有很多个学生。学生也是根据UUID 来区别(把这里的UUID当做学生的【学号】)。当你需要用手机来和蓝牙设备通信的时候,就相当于你想和一个学生交流,你得先知道这个学生的学号,所在班级号,就是开发中的所说的CharacUUID, ServiceUUID。



④BluetoothGattCallback

所有操作的回调函数。以下是我重写了它的方法,总共九个。一会慢慢的介绍。

<pre name="code" class="java"><span style="font-size:12px;"></span><pre name="code" class="java"><span style="font-size:14px;">/** * 所有操作的回调函数。 实现回调方法,监听APP的事件改变。例如,连接和服务发现变化。 *  * <pre> * 1:notification对应 onCharacteristicChanged; * 2:readCharacteristic对应onCharacteristicRead; * 3:writeCharacteristic对应onCharacteristicWrite; * 4:连接蓝牙或者断开蓝牙 对应 onConnectionStateChange; * 5:readDescriptor对应onDescriptorRead; * 6:writeDescriptor对应onDescriptorWrite; * 7:readRemoteRssi对应onReadRemoteRssi; * 8:executeReliableWrite对应onReliableWriteCompleted; * 9:discoverServices对应onServicesDiscovered。 * </pre> */private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {super.onConnectionStateChange(gatt, status, newState);}@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);}@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicRead(gatt, characteristic, status);}@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicWrite(gatt, characteristic, status);}@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {super.onCharacteristicChanged(gatt, characteristic);}@Overridepublic void onDescriptorRead(BluetoothGatt gatt,BluetoothGattDescriptor descriptor, int status) {super.onDescriptorRead(gatt, descriptor, status);}@Overridepublic void onDescriptorWrite(BluetoothGatt gatt,BluetoothGattDescriptor descriptor, int status) {super.onDescriptorWrite(gatt, descriptor, status);}@Overridepublic void onReliableWriteCompleted(BluetoothGatt gatt, int status) {super.onReliableWriteCompleted(gatt, status);}@Overridepublic void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {super.onReadRemoteRssi(gatt, rssi, status);}};</span>

开始来看我们的程序↓↓↓↓

当调用了连接函数 mBluetoothGatt =  bluetoothDevice.connectGatt(this.context, false, gattCallback);之后,

/** * 连接断开的状态改变 */@Overridepublic void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) {super.onConnectionStateChange(gatt, status, newState);// 首先判断这个status 如果等于BluetoothGatt.GATT_SUCCESS(value=0)代表这个回调是正常的,// 如果不等于 0,那边就代表没有成功,也不需要进行其他操作了,// 连接成功和断开连接都会走到这里if (newState == BluetoothProfile.STATE_CONNECTED) {Log.i("连接与断开", "连接 GATT 服务.");// 连接成功之后,我们应该立刻去寻找服务(上面提到的BluetoothGattService),只有寻找到服务之后,才可以和设备进行通信mBluetoothGatt.discoverServices();} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // 断开Log.i("连接与断开", "断开与服务的连接.");}}

 当判断到连接成功之后,会去寻找服务, 这个过程是异步的,会耗点时间,当寻找到服务之后,会走到回调:

/** * 服务发现设备 */@Overridepublic void onServicesDiscovered(BluetoothGatt gatt, int status) {super.onServicesDiscovered(gatt, status);if (status == BluetoothGatt.GATT_SUCCESS) {// 寻找到服务// 寻找服务之后,我们就可以和设备进行通信,比如下发配置值,获取设备电量什么的readBatrery(); // 读取电量操作sendSetting(); // 下发配置值}else {Log.w("服务发现设备", "服务发现收到状态: " + status);}}

接着看读的方法 

/** *  读操作 */private void readBatrery() {// 如上面所说,想要和一个学生通信,先知道他的班级(ServiceUUID)和学号(CharacUUID)BluetoothGattService batteryService = mBluetoothGatt.getService(UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb")); // 此处的0000180f...是举例,实际开发需要询问硬件那边if (batteryService != null) {BluetoothGattCharacteristic batteryCharacteristic = batteryService.getCharacteristic(UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb"));// 此处的00002a19...是举例,实际开发需要询问硬件那边if (batteryCharacteristic != null) { // 读取电量,这是读取batteryCharacteristic值的方法,读取其他的值也是如此,只是它们的ServiceUUID和CharacUUID不一样mBluetoothGatt.readCharacteristic(batteryCharacteristic);}}}

 如果读取电量(或者读取其他值)成功之后 ,会来到回调:

/** * 设备发来的数据 */@Overridepublic void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {super.onCharacteristicRead(gatt, characteristic, status);// 读取到值,根据UUID来判断读到的是什么值if (characteristic.getUuid().toString().equals("00002a19-0000-1000-8000-00805f9b34fb")) {// 获取到电量int battery = characteristic.getValue()[0];}}
接下来看写的方法↓ ↓ ↓

/** * 写操作 */private void sendSetting() {BluetoothGattService sendService = mBluetoothGatt.getService(UUID.fromString("00001805-0000-1000-8000-00805f9b34fb"));// 此处的00001805...是举例,实际开发需要询问硬件那边if (sendService != null) {BluetoothGattCharacteristic sendCharacteristic = sendService.getCharacteristic(UUID.fromString("00002a08-0000-1000-8000-00805f9b34fb"));// 此处的00002a08...是举例,实际开发需要询问硬件那边if (sendCharacteristic != null) {// 随便举个数据sendCharacteristic.setValue(new byte[] { 0x01, 0x20, 0x03 });// 写命令到设备,mBluetoothGatt.writeCharacteristic(sendCharacteristic);}}}

如果下发命令成功后,会来到回调:

/** * write成功(发送值成功) 写入Characteristic成功与否的回调 可以根据 * characteristic.getValue()来判断是哪个值发送成功了,比如 连接上设备之后你有一大串命令需要下发,你调用多次写命令, * 这样你需要判断是不是所有命令都成功了,因为android不太稳定,有必要来check命令是否成功,否则你会发现你明明调用 * 写命令,但是设备那边不响应 */@Overridepublic void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) {switch (status) {// 写入成功case BluetoothGatt.GATT_SUCCESS:Log.d("write回调", "----写入数据成功!");byte[] b = characteristic.getValue();break;// 写入失败case BluetoothGatt.GATT_FAILURE:Log.d("write回调", "----写入数据失败!");break;// 没有写入的权限case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:Log.d("write回调", "----没有写入数据的权限!");break;}}

  讲解完读写操作,还有一个重要操作就是Notify(通知)。notify 就是让设备 可以发送通知给你,也可以说上报值给你(发送命令给你)。

<span style="font-size:14px;">/** * 启用或禁用通知给特征。 *  * @param characteristic *            特点采取行动。 * @param enabled *            如果这为true,启用通知。否则false。 * @return 是否成功开启通知 */public boolean enableNotification(BluetoothGattCharacteristic characteristic, boolean enable) {if (mBluetoothGatt == null || characteristic == null)return false;if (!mBluetoothGatt.setCharacteristicNotification(characteristic,enable))return false;BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("0000fff7-0000-1000-8000-00805f9b34fb"));if (descriptor == null)return false;if (enable) {descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);} else {descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);}return mBluetoothGatt.writeDescriptor(descriptor);}</span>

 一旦设备那边notify 数据给你,你会在回调里收到:

<span style="font-size:14px;">/** * 收到设备notify值 (设备上报值) */@Overridepublic void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {//收到设备notify值 (设备上报值),根据 characteristic.getUUID()来判断是谁发送值给你,根据characteristic.getValue()来获取这个值L.i("收到设备notify值", "收到设备notify值");}</span>

先写到这儿,后续开发在来进行总结。得意


0 0
原创粉丝点击