使用 Android Studio 的蓝牙 LE:使用按钮写入特性

Bluetooth LE with Android Studio: Write Characteristic with buttons

我是 Android 和蓝牙的新手,遇到了这个问题。

如果触摸两个按钮,我想写一个特定的特性。 如果我触摸第一个按钮,0-9 之间的数字应该用 +1 计数。使用另一个按钮,数字应该减少 -1。 作为基础,我使用 Google 中的 BluetootleGatt 示例应用程序。 在 DeviceControlActivity 中,我更改了以下代码:

private final ExpandableListView.OnChildClickListener servicesListClickListner =
        new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
                                        int childPosition, long id) {
                if (mGattCharacteristics != null) {
                    final BluetoothGattCharacteristic characteristic =
                            mGattCharacteristics.get(groupPosition).get(childPosition);
                    final int charaProp = characteristic.getProperties();  //The properties contain a bit mask of property flags indicating
                   //the features of this characteristic.
                   if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                        // If there is an active notification on a characteristic, clear
                        // it first so it doesn't update the data field on the user interface.
                        if (mNotifyCharacteristic != null) {
                            mBluetoothLeService.setCharacteristicNotification(
                                    mNotifyCharacteristic, false);
                            mNotifyCharacteristic = null;
                        }
                      mBluetoothLeService.readCharacteristic(characteristic);
                    }
                    if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY ) > 0) {

                        mNotifyCharacteristic = characteristic;
                        mBluetoothLeService.setCharacteristicNotification(
                                characteristic, true);
                    }

                    if ((charaProp | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                        characteristic.setWriteType(BluetoothGattCharacteristic.PERMISSION_WRITE);
                        addListenerOnButton();

                    }

                    return true;
                }
                return false;
            }
};

这是我的两个按钮的 addListenerOnButton():

public void addListenerOnButton() {

    mArrowUp = (ImageButton) findViewById(R.id.arrow_up);
    mArrowUp.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
          mBluetoothLeService.writeCharacteristicUp();

        }

    });

    mArrowDown = (ImageButton) findViewById(R.id.arrow_down);
    mArrowDown.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
        mBluetoothLeService.writeCharacteristicDown();
        }

    });

}

他们会调用BluetoothLeService-Class中的两个writeCharacteristic方法。例如我 post 这里只有 writeCharacteristicUp()-Method:

public boolean writeCharacteristicUp() {

    //check mBluetoothGatt is available
    if (mBluetoothGatt == null) {
        Log.e(TAG, "lost connection");
        return false;
    }
    BluetoothGattService Service = mBluetoothGatt.getService(UUID_DO_LOGGER_TEST);
    if (Service == null) {
        Log.e(TAG, "service not found!");
        return false;
    }
    BluetoothGattCharacteristic charac = Service
            .getCharacteristic(UUID_TEST_NUMBER);
    if (charac == null) {
        Log.e(TAG, "char not found!");
        return false;
    }

    byte[] value0 = new byte[1];
    value0[0] = (byte) 0;   //Constant of 0 for comparison later
    byte[] value1 = new byte[1];
    value1[0] = (byte) 1;  //Constant of 1 for comparison later
    byte[] value2 = new byte[1];
    value2[0] = (byte) 2;  //Constant of 1 for comparison later
    byte[] value3 = new byte[1];
    value3[0] = (byte) 3;  //Constant of 1 for comparison later
    byte[] value4 = new byte[1];
    value4[0] = (byte) 4;  //Constant of 1 for comparison later
    byte[] value5 = new byte[1];
    value5[0] = (byte) 5;  //Constant of 1 for comparison later
    byte[] value6 = new byte[1];
    value6[0] = (byte) 6;  //Constant of 1 for comparison later
    byte[] value7 = new byte[1];
    value7[0] = (byte) 7;  //Constant of 1 for comparison later
    byte[] value8 = new byte[1];
    value8[0] = (byte) 8;  //Constant of 1 for comparison later
    byte[] value9 = new byte[1];
    value9[0] = (byte) 9;  //Constant of 1 for comparison later

    byte[] actualvalue = charac.getValue();

    if (actualvalue == value0) {
        charac.setValue(value1);
    }
    if (actualvalue == value1) {
        charac.setValue(value2);
    }
    if (actualvalue == value2) {
        charac.setValue(value3);
    }
    if (actualvalue == value3) {
        charac.setValue(value4);
    }
    if (actualvalue == value4) {
        charac.setValue(value5);
    }
    if (actualvalue == value5) {
        charac.setValue(value6);
    }
    if (actualvalue == value6) {
        charac.setValue(value7);
    }
    if (actualvalue == value7) {
        charac.setValue(value8);
    }
    if (actualvalue == value8) {
        charac.setValue(value9);
    }
    if (actualvalue == value9) {
        charac.setValue(value0);
    } 
  //  charac.setValue(value0);
  //  byte[] actualvaluenew1 = charac.getValue();
    boolean status = mBluetoothGatt.writeCharacteristic(charac);
  //  byte[] actualvaluenew2 = charac.getValue();
    return status;
}

问题是

boolean status = mBluetoothGatt.writeCharacteristic(charac)  

不起作用,状态将为假。因此实际值不会显示在相应 TextView 的屏幕上。为什么? 我还发现 if-grinds 不起作用,因为 charac.setValue(value0) 仅在 if-grinds 之外工作?

我建议您按住 control 键并单击代码中的 BluetoothGatt#writeCharacteristic(ch) 函数。然后 Android Studio 将查看 BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic characteristic) 函数:

    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
    if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
        && (characteristic.getProperties() &
            BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false;

    if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
    if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;

    BluetoothGattService service = characteristic.getService();
    if (service == null) return false;

    BluetoothDevice device = service.getDevice();
    if (device == null) return false;

    synchronized(mDeviceBusy) {
        if (mDeviceBusy) return false;
        mDeviceBusy = true;
    }

    try {
        mService.writeCharacteristic(mClientIf, device.getAddress(),
            service.getType(), service.getInstanceId(),
            new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
            new ParcelUuid(characteristic.getUuid()),
            characteristic.getWriteType(), AUTHENTICATION_NONE,
            characteristic.getValue());
    } catch (RemoteException e) {
        Log.e(TAG,"",e);
        mDeviceBusy = false;
        return false;
    }

    return true;
}

在方法中打断点并进行调试。以下是根据源代码得到false的可能原因:

  1. 远程 BLE 设备没有 WriteWrite with No Response 访问权限
  2. 要么你的服务为空,要么你设置的特征值为空
  3. 您的设备已经在与远程设备进行另一个 BLE 进程

在我看来,最有可能是第二条原因。