BLE 外围设备和 BLE 中央设备

BLE Peripheral & BLE Central

我正在使用 BLE Android 到 iOS 开发一个聊天应用程序, 现在我正在使用以下两个库作为参考

https://github.com/izumin5210/Bletia

https://github.com/captain-miao/bleYan

我面临的问题是当外围设备写入任何特征时,中央设备 (Android) 中的 BLECallback 不会被调用。

我的回调代码

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        BleLog.i(TAG, "onConnectionStateChange: State = " + BleUtils.getBleConnectStatus(status)
                + " newState = " + BleUtils.getBleConnectStatus(newState));

        if (newState == BluetoothProfile.STATE_CONNECTED) {
            updateState(BleConnectState.CONNECTED);
            //开始发现服务
            BleLog.i(TAG, "gatt.discoverServices()");
            gatt.discoverServices();
        } else if (newState == BluetoothProfile.STATE_CONNECTING) {
            updateState(BleConnectState.CONNECTING);
        } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
            updateState(BleConnectState.DISCONNECTING);
        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            //断开了,需要做什么处理?
            sIsWriting = false;
            sWriteQueue.clear();
            updateState(BleConnectState.DISCONNECTED);
        }
    }

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

        if (status == BluetoothGatt.GATT_SUCCESS) {
            onDiscoverServices(gatt);
            //需要返回 gatt
            updateState(BleConnectState.SERVICE_IS_DISCOVERED);
        } else {
            BleUtils.refreshDeviceCache(mGatt);
            //失败 需要做何处理 129
            if(mState != BleConnectState.SERVICE_IS_NOT_DISCOVERED) {
                updateState(mState);
            }
        }

        //MSG_BLE_ID_SERVICES_DISCOVERED
        Message msg = Message.obtain();
        msg.what = BleConstants.MSG_BLE_ID_SERVICES_DISCOVERED;
        msg.arg1 = status;
        msg.obj = gatt;
        notifyAllBleClients(msg);
        BleLog.i(TAG, "onServicesDiscovered: " + BleUtils.getGattStatus(status));
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic, int status) {
        BleLog.i(TAG, "onCharacteristicWrite: " + BleUtils.getGattStatus(status));
        UUID uuid = characteristic.getUuid();
        sendBleMessage(BleConstants.MSG_BLE_ID_CHARACTERISTIC_WRITE, status, uuid);
        onNextWrite();
    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt,
            BluetoothGattDescriptor descriptor, int status) {
        BleLog.i(TAG, "onDescriptorWrite: " + BleUtils.getGattStatus(status));
        UUID uuid = descriptor.getUuid();

        sendBleMessage(BleConstants.MSG_BLE_ID_DESCRIPTOR_WRITE, status, uuid);
        onNextWrite();
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        final byte[] data = characteristic.getValue();
        BleLog.i(TAG, "onCharacteristicChanged: " + HexUtil.encodeHexStr(data));
        UUID uuid = characteristic.getUuid();

        sendBleMessage(BleConstants.MSG_BLE_ID_CHARACTERISTIC_NOTIFICATION, BluetoothGatt.GATT_SUCCESS, data, uuid);
        onNextWrite();
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        final byte[] data = characteristic.getValue();
        System.out.println(TAG +" onCharacteristicRead: " + data);

        if(data != null) {
            final StringBuilder stringBuilder = new StringBuilder(data.length);
            for (byte byteChar : data)
                stringBuilder.append(String.format("%02X ", byteChar));

            final String values = stringBuilder.toString();

            BleLog.i(TAG, "onCharacteristicRead: " + new String(data));
        }else{
            BleLog.i(TAG, " onCharacteristicRead: " + "NULL");
        }

        UUID uuid = characteristic.getUuid();

        sendBleMessage(BleConstants.MSG_BLE_ID_CHARACTERISTIC_READ, status, data, uuid);
        onNextWrite();
    }

    @Override
    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        final byte[] data = descriptor.getValue();

        if(data != null) {
            final StringBuilder stringBuilder = new StringBuilder(data.length);
            for (byte byteChar : data)
                stringBuilder.append(String.format("%02X ", byteChar));

            final String values = stringBuilder.toString();

            BleLog.i(TAG, "onDescriptorRead: " + new String(data, Charset.defaultCharset()));
        }else{
            BleLog.i(TAG, " onDescriptorRead: " + "NULL");
        }
        UUID uuid = descriptor.getUuid();

        sendBleMessage(BleConstants.MSG_BLE_ID_DESCRIPTOR_READ, status, data, uuid);
        onNextWrite();
    }

    @Override
    public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
        BleLog.i(TAG, "onReliableWriteCompleted: " + BleUtils.getGattStatus(status));

        Message msg = Message.obtain();
        msg.what = BleConstants.MSG_BLE_ID_RELIABLE_WRITE_COMPLETED;
        msg.arg1 = status;
        notifyAllBleClients(msg);
        onNextWrite();
    }

    @Override
    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        BleLog.i(TAG, "onReadRemoteRssi: " + rssi + " status:" + BleUtils.getGattStatus(status));

        Message msg = Message.obtain();
        msg.what = BleConstants.MSG_BLE_ID_READ_REMOTE_RSSI;
        msg.arg1 = status;
        msg.arg2 = rssi;
        notifyAllBleClients(msg);
        onNextWrite();
    }

    @Override
    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
        BleLog.i(TAG, "onMtuChanged: " + BleUtils.getGattStatus(status));

        Message msg = Message.obtain();
        msg.what = BleConstants.MSG_BLE_ID_MTU_CHANGED;
        msg.arg1 = status;
        msg.arg2 = mtu;
        notifyAllBleClients(msg);
        onNextWrite();
    }
};

iOS 通知代码

    if (myPeripheral.connectedToPeer)
    {
        CBCharacteristic *peerAvailable = [myPeripheral findCharacteristicFromUUID:myPeripheral.notifyPeerAvailableUUID];
        if (peerAvailable && !peerAvailable.isNotifying) {
            [myPeripheral.cbPeripheral setNotifyValue:YES forCharacteristic:peerAvailable];
        }

        CBCharacteristic *peerReceiveMessage = [myPeripheral findCharacteristicFromUUID:myPeripheral.peerSendToCentralFromPeripheralUUID];
        if (peerReceiveMessage && !peerReceiveMessage.isNotifying) {
            [myPeripheral.cbPeripheral setNotifyValue:YES forCharacteristic:peerReceiveMessage];
        }

    }

外围设备应使用bluetoothGattServer.notifyCharacteristicChanged

通知特性已更改

Android 中央设备应订阅通知。

if (characteristic != null) {
                        //SetNotification
                        Log.i(TAG, "SetNotification");
                        gatt.setCharacteristicNotification(characteristic, true);
                        for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
                            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                            gatt.writeDescriptor(descriptor);
                        }

在peripheral中,你写的Characteristic应该有NOTIFY属性,central应该使用setCharacteristicNotification函数来监听characteristic的变化。当值改变时,会触发onCharacteristicChanged回调。