如何在 android 应用程序上从 BLE 设备接收数据

How to receive data from BLE device on android app

我是 android studio 和创建应用程序的新手,这是我正在做的项目的一部分。

我能够连接到蓝牙设备并能够将其置于状态为 GATT_SUCCESS 的 onServicesDiscovered 函数中。

我不知道从这里去哪里,因为我没有从设备接收数据。我是否需要广播更新或广播接收器,或者下面的代码是否正常但需要修复?

如果有人能提供帮助那就太好了!

@Override
        //New services discovered
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.i("onServicesDiscovered", "Status: " + status);
            if(status == GATT_SUCCESS) {
                List<BluetoothGattService> services = gatt.getServices();
                
                for(BluetoothGattService service : services){
                    if(!service.getUuid().equals("49535343-FE7D-4AE5-8FA9-9FAFD205E455"))
                        continue;
                    List<BluetoothGattCharacteristic> gattCharacteristics = service.getCharacteristics();

                    // Loops through available Characteristics
                    for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics){
                        if(!gattCharacteristic.getUuid().equals("49535343-1E4D-4BD9-BA61-23C647249616"))
                            continue;

                        final int charaProp = gattCharacteristic.getProperties();

                        if((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0){
                            setCharacteristicNotification(gattCharacteristic, true);
                            Log.w(TAG, "Working");
                        }else{
                            Log.w(TAG, "Characteristic does not support notify");
                        }
                    }
                }
            }else{
                Log.w(TAG, "onServicesDiscovered receive: " + status);
            }
                //List<BluetoothGattService> services = gatt.getServices();
                //Log.i("onServicesDiscovered", services.toString());
                //gatt.readCharacteristic(services.get(1).getCharacteristics().get(0));
            
        }

        @Override
        //Result of a characteristic read operation
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.i("onCharacteristicRead", characteristic.toString());
            if(status != GATT_SUCCESS){
                Log.e(TAG, String.format(Locale.ENGLISH, "ERROR: Read failed for characteristic: %s, status %d", characteristic.getUuid(), status));
                completedCommand();
                return;
            }
            //gatt.disconnect();
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if (status == GATT_SUCCESS) {
                if (descriptor.getCharacteristic().getUuid().equals(UUID_TARGET_CHARACTERISTIC)) {
                    Log.i(TAG, "Successfully subscribed");
                }

                byte[] data = {1, 1};
                BluetoothGattService Service = mGatt.getService(UUID_TARGET_SERVICE);

                BluetoothGattCharacteristic charac = Service.getCharacteristic(UUID_TARGET_CHARACTERISTIC);

                charac.setValue(data);
                mGatt.readCharacteristic(charac);
            } else {
                Log.e(TAG, "Error subscribing");
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            byte[] value = characteristic.getValue();
            Log.i("BLE", "receive value ----------------------------");
            for (int i = 0; i < value.length; i++) {
                Log.w("BLE", "character_value = " + value[i]);
            }
            //processData(characteristic.getValue());
        }
    };

    public boolean readCharacteristic(final BluetoothGattCharacteristic characteristic) {
        if(mGatt == null) {
            Log.e(TAG, "ERROR: Gatt is 'null', ignoring read request");
            return false;
        }

        // Check if characteristic is valid
        if(characteristic == null) {
            Log.e(TAG, "ERROR: Characteristic is 'null', ignoring read request");
            return false;
        }

        // Check if this characteristic actually has READ property
        if((characteristic.getProperties() & PROPERTY_READ) == 0 ) {
            Log.e(TAG, "ERROR: Characteristic cannot be read");
            return false;
        }

        // Enqueue the read command now that all checks have been passed
        boolean result = commandQueue.add(new Runnable() {
            @Override
            public void run() {
                if(!mGatt.readCharacteristic(characteristic)) {
                    Log.e(TAG, String.format("ERROR: readCharacteristic failed for characteristic: %s", characteristic.getUuid()));
                    completedCommand();
                } else {
                    Log.d(TAG, String.format("reading characteristic <%s>", characteristic.getUuid()));
                    nrTries++;
                }
            }
        });

        if(result) {
            nextCommand();
        } else {
            Log.e(TAG, "ERROR: Could not enqueue read characteristic command");
        }
        return result;
    }

    private void nextCommand() {
        // If there is still a command being executed then bail out
        if(commandQueueBusy) {
            return;
        }

        // Check if we still have a valid gatt object
        if (mGatt == null) {
            Log.e(TAG, String.format("ERROR: GATT is 'null' for peripheral '%s', clearing command queue", device.getAddress()));
            commandQueue.clear();
            commandQueueBusy = false;
            return;
        }

        // Execute the next command in the queue
        if (commandQueue.size() > 0) {
            final Runnable bluetoothCommand = commandQueue.peek();
            commandQueueBusy = true;
            nrTries = 0;

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        bluetoothCommand.run();
                    } catch (Exception ex) {
                        Log.e(TAG, String.format("ERROR: Command exception for device '%s'", device.getName()), ex);
                    }
                }
            });
        }
    }

    private void retryCommand() {
        commandQueueBusy = false;
        Runnable currentCommand = commandQueue.peek();
        if(currentCommand != null) {
            if (nrTries >= MAX_TRIES) {
                // Max retries reached, give up on this one and proceed
                Log.v(TAG, "Max number of tries reached");
                commandQueue.poll();
            } else {
                //isRetrying = true;
            }
        }
        nextCommand();
    }

    private void completedCommand() {
        commandQueueBusy = false;
        //isRetrying = false;
        commandQueue.poll();
        nextCommand();
    }

    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
        if (bluetoothAdapter == null || mGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mGatt.setCharacteristicNotification(characteristic, enabled);

        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(BTMODULEUUID);
        descriptor.setValue(enabled?BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE :BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        mGatt.writeDescriptor(descriptor);

    }

您似乎想打开通知以从您的 BLE 设备接收数据,并且您使用了 setCharacteristicNotification(gattCharacteristic, true); 来达到这个目的。但这还不够。它只会告诉蓝牙堆栈此特性将发送通知,但您还想在设备上订阅通知。

为此你需要所谓的 CCC 描述符并向其写入 ENABLE_NOTIFICATION_VALUE:

private final String CCC_DESCRIPTOR_UUID = "00002902-0000-1000-8000-00805f9b34fb";
final BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(UUID.fromString(CCC_DESCRIPTOR_UUID));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);

同时执行这两项操作将为该设备启用通知。看看来自 PunchTrough 的这个很棒的 Guide,了解有关使用 BLE 的更多信息。