Ble4.0 APP开发总结

Ble4.0 APP开发总结

最近自学了一个多礼拜的蓝牙ble开发,对这方面有些粗略的理解,及时做个总结,不对的地方希望大家帮忙揪出来。

首先介绍几个类 :BluetoothGatt,BluetoothGattService,BluetoothGattCharacteristic,BluetoothGattCallback

BluetoothGatt

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

BluetoothGatt 是通过蓝牙设备连接获得:
bluetoothDevice.connectGatt(this.context, false, gattCallback);

先来谈一下这个方法:
android.bluetooth.BluetoothDevice.connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)

第一个参数context不说
第二个autoConnect

为false 立刻发起一次连接为true 自动连接,只要蓝牙设备变得可用实测发现,用false连接比较好,比较快, true会等个十几秒甚至几分钟才会连接上。 开发过程中一般都是用false,扫描到bluetoothdevice之后,直接用false连接即可。

第三个BluetoothGattCallback

是非常重要的回调函数,手机与蓝牙设备的一切通信结果都在这里体现。待会仔细分析。

BluetoothGattService

蓝牙设备所拥有的服务。在这里比喻成 班级 吧。bluetoothdevice就比喻成学校吧。 一个学校可以有很多个班级。班级 根据UUID来区别。

BluetoothGattCharacteristic

蓝牙设备所拥有的特征。比喻成 学生。一个班级里也可以有很多个学生。学生也是根据UUID 来区别
当你需要用手机来和蓝牙设备通信的时候,就相当于 你想 和一个学生交流,你得先知道 这个学生的学号,所在班级号,就是开发中的所说的CharacUUID, ServiceUUID。这个uuid就是相当于网络中的端口号,蓝牙的mac地址就是相当于网络中的ip地址,只不过uuid是具体的分了一层,首先需要CharacUUID得到一个大方向的集合,然后再加 ServiceUUID得到具体的功能。

BluetoothGattCallback

所有操作的回调函数。

          private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {

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

            super.onCharacteristicChanged(gatt, characteristic);
            //收到设备notify值 (设备上报值)
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            //读取到值

        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                                          BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //write成功(发送值成功)
            }

        }

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                            int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothGatt.STATE_CONNECTED) {
                    // 连接成功

                } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
                    // 断开连接

                }
            }
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt,
                                     BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt,
                                      BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);

        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //获取到RSSI,  RSSI 正常情况下 是 一个 负值,如 -33 ; 这个值的绝对值越小,代表设备离手机越近
                //通过mBluetoothGatt.readRemoteRssi();来获取
            }
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
        }

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

            if (status == BluetoothGatt.GATT_SUCCESS) {
                //寻找到服务
            }
        }
    };

当调用了连接函数 mBluetoothGatt = bluetoothDevice.connectGatt(this.context, false, gattCallback);之后, 如果连接成功就会 走到 连接状态回调:

   @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                        int newState) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            //首先判断这个status如果等于BluetoothGatt.GATT_SUCCESS(value=0)代表这个回调是正常的,
            //如果不等于 0,那边就代表没有成功,也不需要进行其他操作了,
            // 连接成功和断开连接都会走到这里
            if (newState == BluetoothGatt.STATE_CONNECTED) {
                // 连接成功


                //连接成功之后,我们应该立刻去寻找服务(上面提到的BluetoothGattService),只有寻找到服务之后,才可以和设备进行通信
                gatt.discoverServices();// 寻找服务
            } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
                // 断开连接
            }

        }
    }

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

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

        if (status == BluetoothGatt.GATT_SUCCESS) {
            //寻找到服务
            //寻找服务之后,我们就可以和设备进行通信,比如下发配置值,获取设备电量什么的

            //具体操作           
            readBatrery();  //读取电量操作
            sendSetting(); //下发配置值

        }
    }

    /***
     * 读操作
     ***/
   public  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不一样

            }
        }
    }

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

     @Override
    public 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];
        }

    }

    /***
     * 写操作
     ***/
    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);//写命令到设备, 
            }
        }
    }

如果下发配置成功之后,会来到回调:

        @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
        if (status == BluetoothGatt.GATT_SUCCESS) {
            //write成功(发送值成功),可以根据 characteristic.getValue()来判断是哪个值发送成功了,比如 连接上设备之后你有一大串命令需要下发,你调用多次写命令, 这样你需要判断是不是所有命令都成功了,因为android不太稳定,有必要来check命令是否成功,否则你会发现你明明调用 写命令,但是设备那边不响应
        }

    }

讲解完读写操作,还有一个重要操作 就是 Notify(通知)
notify 就是让设备 可以发送通知给你,也可以说上报值给你(发送命令给你)
首先你得打开设备的通知功能:

 //参数 enable 就是打开还是关闭, characteristic就是你想让具有通知功能的BluetoothGattCharacteristic 
    private boolean enableNotification(boolean enable, BluetoothGattCharacteristic characteristic) {
        if (mBluetoothGatt == null || characteristic == null)
            return false;
        if (!mBluetoothGatt.setCharacteristicNotification(characteristic,
                enable))
            return false;
        BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUIDUtils.CCC);
        if (clientConfig == null)
            return false;

        if (enable) {
            clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else {
            clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        }
        return mBluetoothGatt.writeDescriptor(clientConfig);
    }

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

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

        super.onCharacteristicChanged(gatt, characteristic);
        //收到设备notify值 (设备上报值),根据 characteristic.getUUID()来判断是谁发送值给你,根据 characteristic.getValue()来获取这个值
    }

关于发送命令

比如刚连接上设备,你会把很多配置都发送给设备,此时可能会调用多次 write操作,这个时候你应该需要在 write操作之间 加点间隔 例如开启线程,用 Thread.sleep(150), 因为只有收到onCharacteristicWrite回调之后才代表你的值成功了,如果不加间隔,你会发现可能只会成功一个值。目前测试下来,我才用的是间隔150毫秒比较好,不会太慢,成功率也会高, 可自己实践慢慢调试,这个数值还与设备端update速率有关在Write 操作的时候,还有个办法可以增快下发速度,且不需要加sleep就是设置:

characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); 

就是不需要回复,这样速度会快,还是有点可靠的。各位可斟酌使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值