当前位置: 首页 > 知识库问答 >
问题:

Android BLE write特性锁定

斜浩穰
2023-03-14

我有一个消息线程用于发送消息缓冲区。一旦onCharacteristicWrite成功,每个消息就会排队发送,然后特征就会写入下一条消息。characeeristic还设置为write_type_no_response,因此在特征写调用之间消息缓冲区队列非常快(大约0-7毫秒)。

有时我会在onConnectionStateChange中得到一个状态为8的回调,设备超出范围。但这种情况并不总是发生。

消息线程代码:

    private boolean stopMessageThread = false;
    private boolean characteristicWriteSuccessful = true;
    private ArrayList<byte[]> messageQueue = new ArrayList<byte[]>();
    private Thread messageThread =  new Thread( new Runnable() {
        private long lastTime = 0;
        private int count = 0;
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted() && !stopMessageThread) {
                if(messageQueue.size() != 0 && characteristicWriteSuccessful) {

                    Log.i(TAG, ""+(System.currentTimeMillis()-lastTime));
                    Log.i(TAG, "Queue count: "+messageQueue.size());

                    characteristicWriteSuccessful = false;
                    byte[] message = messageQueue.remove(0);
                    customCharacteristic.setValue(message);
                    boolean status = bluetoothGatt.writeCharacteristic(customCharacteristic);

                    Log.i(TAG, "write characteristic status "+status);

                    lastTime = System.currentTimeMillis();
                    //sleep(10); // this kinda helps but can still throw the error
                }
            }
        }
    });

共有1个答案

邢冷勋
2023-03-14

除了繁忙的等待,这可能会阻塞整个CPU和快速耗尽电池,我看不到任何同步。有共享数据结构(可能是StopMessageThreadCharacteristicWriteSuccessfulMessageQueue)和几个线程访问它们。如果没有同步,就会出现争用情况,而阻塞可能就是这种情况的一种表现。

因此,我建议采用更简单的设计,尤其是没有用于发送消息的线程:

private ArrayList<byte[]> messageQueue = new ArrayList<byte[]>();
private boolean isSending = false;

void sendMessage(byte[] message) {
    synchronized (this) {
        if (isSending) {
            messageQueue.add(message);
            return;
        }
        isSending = true;
    }
    customCharacteristic.setValue(message);
    bluetoothGatt.writeCharacteristic(customCharacteristic);
}

public void onCharacteristicWrite (BluetoothGatt gatt, 
                BluetoothGattCharacteristic characteristic, 
                int status) {
    byte[] message;
    synchronized (this) {
        if (messageQueue.size() == 0) {
            isSending = false;
            return;
        }
        message = messageQueue.remove(0);
    }
    customCharacteristic.setValue(message);
    bluetoothGatt.writeCharacteristic(customCharacteristic); 
}

此解决方案中的假设是WriteCharacteristic不会阻塞并且速度很快。这是一个安全的假设,因为该方法在设计上是异步的:它有一个回调,当操作完成时将被调用。

因此,回调oncharacteristicwrite用于发送缓冲区中的下一条消息。因此,对线程的需求消失了--相关的复杂性也消失了。

由于回调是从后台线程调用的,仍然涉及到几个线程。因此,对共享数据的访问是同步的。

 类似资料:
  • 我想为strerror\u r调用创建线程本地缓冲区,并编写自己的线程安全字符*my\u strerror(int),它将使用线程本地缓冲区并调用strerror\r。 当阅读R. Stevens在Unix环境高级编程中关于pthread_getspecific()的例子时,我觉得差异-为什么在下面的例子中使用互斥锁? 书中的例子:

  • 我从这个链接(Mifare Ultralight C Lock)获得了参考,使Mifare Ultralight标签上的所有页面都是只读的。 我可以在Android上成功地在Mi的Ultralight标签上写入消息。现在我想锁定第4到7页(或任何特定页面)。上面的链接只显示了如何锁定所有页面。我如何锁定特定页面? 此代码锁定所有页面:

  • Spring Cloud专注于提供良好的开箱即用经验的典型用例和可扩展性机制覆盖。 分布式/版本化配置 服务注册和发现 路由 service - to - service调用 负载均衡 断路器 分布式消息传递

  • 1、基于Workerman开发 GatewayWorker是基于Workerman开发的 2、基于Gateway、Worker进程模型 GatewayWorker使用经典的Gateway和Worker进程模型。Gateway进程负责维持客户端连接,并转发客户端的数据给Worker进程处理;Worker进程负责处理实际的业务逻辑,并将结果推送给对应的客户端。Gateway服务和Worker服务可以分

  • Free但不开源(目前已经开源) Build(构建)和 debug(调试) 现代web和云应用(尤其是JavaScript、TypeScript、C#、ASP.NET v5 和 Nodejs) 跨平台支持Linux, Mac OSX, and Windows 支持语法自动补全,智能提示 内置html开发神器emmet 速度、调试效率非常快 支持多主题(配色方案)0.9.1之后更爽 对于其他编辑器的

  • 特性给有关声明或类型提供更多的信息。在 Swift 中有两种特性,一种用于声明,另一种用于类型。 通过在 @ 符号后跟一个特性名称和该特性可以接受的实际参数来指定一个特性: @ attribute name @ attribute name ( attribute arguments ) 一些接受实际参数的声明特性指定了更多关于它的信息和它们如何应用到特定的声明中。这些特性实际参数写在一对括号里