【问题标题】:writeCharacteristic() returns true, but does not call onCharacteristicWrite()writeCharacteristic() 返回 true,但不调用 onCharacteristicWrite()
【发布时间】:2015-05-24 04:38:55
【问题描述】:

我希望读取存储在设备中的特征值,修改该值,然后将其写入设备。出于某种原因,writeCharacteristic() 返回 true,但内部设备值没有改变,也没有调用 onCharacteristicWrite()。事实上,出于某种原因,它在我尝试编写某些内容时被调用,然后在我关闭或重新打开应用程序后不久被调用 - 并且不会更改设备值。我已经研究了几天,这让我发疯了。值得注意的是,手动和通过通知读取特征都可以正常工作。

为什么writeCharacteristic() 没有通过,为什么onCharacteristicWrite() 在如此奇怪的时间被调用?

我不确定问题出在哪里。这可能是一些愚蠢而简单的事情,比如错误地调用writeCharacteristic()(我的实现基于问题“Working with BLE Android 4.3 how to write characteristics?”)。是否有可能因为onCharacteristicRead() 未完成而忽略该请求?

我认为这些链接似乎最有助于指出问题,但我自己无法从中提取任何内容:

作为我的代码的演练,onItemClick() 事件被触发,它启动了序列。

int flag = 1;
((MainActivity)getActivity()).BtService.readFlag(flag);

它调用一个函数(在Service 中)验证蓝牙连接并读取特征。

public boolean readFlag(int flag){
    /*... removed code here verifies that the Bluetooth Gatt is available,
    that the Service exists...*/

    BluetoothGattCharacteristic characteristic = Service.getCharacteristic(SEND_FLAGS_CHAR);

    if (characteristic == null) {
        Log.e(TAG, "char not found!");
        return false;
    }

    try {
        // Store intended flag value in SharedPreferences, then read the current one.
        Editor fEditor = sPrefs.edit();
        fEditor.putInt(calibrationSetFlagToSendKey, flag);
        fEditor.commit();

        mConnectedGatt.readCharacteristic(characteristic);

        // Catch response in onCharacteristicRead() callback.
        return true;
    }
    catch (NullPointerException e) {
        Log.w("readCharacteristic", "The characteristic could not be read.");
        return false;
    }
}

调用onCharacteristicRead(),它只调用一个Handler来修改并将结果广播回MainActivitytrueFlagValue 是一个全局存储在 Service 中的字节(我知道这是不好的做法,但我打算稍后修改。)

case MSG_SEND_FLAG:
    characteristic = (BluetoothGattCharacteristic) msg.obj;
    if (characteristic.getValue() == null) {
        Log.w(TAG, "Error obtaining current flags");
        return;
    }

    int recentReadDeviceFlag = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
    int initialFlag = sPrefs.getInt(calibrationSetFlagToSendKey, 0);
    if (initialFlag == 0) Log.e("Write Debug", "Flag to send is apparently 0");

    /*... Arithmetic modifying flag integer value...*/
    //Desired value is the OR'd value of the value read and value desired
    trueFlagValue = (byte) ((byte) initialFlag | (byte) recentReadDeviceFlag);
    Log.d("Read Debug", "OR'd value is " + trueFlagValue +", sending broadcast");
    Intent fIntent = new Intent("com.example.appwithble.SEND_FLAGS");
    sendBroadcast(fIntent);
    break;

MainActivity 中的BroadcastReceiver 然后调用我的Service 中的一个方法,验证请求writeCharacteristic(),就像对readCharacteristic() 所做的那样。访问之前设置的trueFlagValue

    else if("com.example.appwithble.SEND_FLAGS".equals(intent.getAction())) {
        BtService.performWriteFlag();
    }

// ...

public boolean performWriteFlag () {
    /*... check Gatt is available and that Service exists...*/
    BluetoothGattCharacteristic characteristic = Service.getCharacteristic(SEND_FLAGS_CHAR);

    if (characteristic == null) {
        Log.e(TAG, "char not found!");
        return false;
    }

    byte[] byteValue = new byte[1];
    byteValue[0] = trueFlagValue;
    characteristic.setValue(byteValue);

    boolean status = mConnectedGatt.writeCharacteristic(characteristic);
    return status;
}

然后应该调用我的onCharacteristicWrite() 回调,目前只包含一行代码来记录一条消息。实际上,只有在应用程序关闭或重新打开时才会调用它。存储在我的外围设备特性中的值永远不会改变。

【问题讨论】:

    标签: android bluetooth bluetooth-lowenergy


    【解决方案1】:

    我不是专家,但在我的 BLE 应用中

    • 我首先连接到外围设备
    • 然后与之配对(通过调用createBond()方法),
    • 然后发现服务,
    • 然后发现特征(并将它们存储在应用变量中)和
    • 最终将值写入特征(通过使用应用程序变量)

    你试过了吗?

    【讨论】:

    • 我还没有尝试实现任何类型的配对——不过剩下的过程已经完成了。我让用户选择一个设备并与 device.connectGatt 连接,读取/存储所有特征并设置通知器。我可以做到这两点,我可以阅读命令,为通知程序设置描述符,并在onCharacteristicChanged() 中接收特征。我不相信 Pairing 对编写是必要的,但由于这是我打算稍后实现的东西,所以现在尝试不会对我造成伤害。我会告诉你它是否有效。
    【解决方案2】:

    这样的菜鸟错误。

    在我认为写入过程或设备出现问题之前,我没有尝试过写入数据。在查看了来自readCharacteristic() 的数据类型并四处询问我发送到的设备后,我开始意识到我发送的数据可能格式错误。

    事实证明,即使只需要发送四个不同的标志(可以用两位完成),对于我的特定设备,特性需要格式化为 两个字节,而不是一个.所以如果我把我的字节数组做成这样,它就可以工作了。

    byte[] byteValue = new byte[2];
    byteValue[0] = trueFlagValue;
    byteValue[1] = (byte)0;
    characteristic.setValue(byteValue);
    

    我预计如果其他人在写入已启动但未完成时遇到奇怪的问题,那么很可能是这样的问题 - 至少,设备中的某些东西正在拒绝写入。

    【讨论】:

    • 我的问题是这个回调在 4.3 设备中工作,但在棒棒糖设备中没有触发
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-30
    • 2016-02-22
    • 2022-06-15
    • 1970-01-01
    • 2012-10-28
    相关资源
    最近更新 更多