Android——BLE通讯开发

最近穿戴设备发展得很火,我们公司也正在做健康类的穿戴设备,因此有机会研究了一把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开发的理解,不喜勿喷!!! 转载请说明出处~谢谢~~

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值