java – Android BLE:onCharacteristicRead()似乎被线程阻止

我正在针对BLE设备实现一系列特征读取.因为readCharacteristic()异步执行,并且因为我们必须等待直到完成才发出另一个“读”调用,所以我用了一个锁来等待()然后在’onCharacteristicRead()中我通知()锁,让事情再次发生.

当我等待()调用readCharacteristic()后,我从未得到onCharacteristicRead()的调用.如果我不等待(),那么我会调用onCharacteristicRead()并且报告正确的值.

这是相关的代码似乎阻止对onCharacteristicRead()的回调:

private void doRead() {
    //....internal accounting stuff up here....
    characteristic = mGatt.getService(mCurrServiceUUID).getCharacteristic(mCurrCharacteristicUUID);
    isReading = mGatt.readCharacteristic(characteristic);

    showToast("Is reading in progress? " + isReading);

    showToast("On thread: " + Thread.currentThread().getName());

    // Wait for read to complete before continuing.
    while (isReading) {
        synchronized (readLock) {
            try {
                readLock.wait();
            } catch (InterruptedException e) {
                e.printstacktrace();
            }
        }
    }
}

public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {
    showToast("onCharacteristicRead()");
    showToast("On thread: " + Thread.currentThread().getName());

    byte[] value = characteristic.getValue();
    StringBuilder sb = new StringBuilder();
    for (byte b : value) {
        sb.append(String.format("%02X",b));
    }

    showToast("Read characteristic value: " + sb.toString());

    synchronized (readLock) {
        isReading = false;
        readLock.notifyAll();
    }
}

如果我只是删除上面的while()语句,我成功地得到读回调.当然,这阻止我等待进一步阅读,所以我不能等待前进.

由于readCharacteristic()是异步的,为什么执行调用线程与实际执行读取的能力有关,还是调用回调的能力?

为了使事情变得更加混乱,我会在调用readCharacteristic()时以及onCharacteristicRead()被调用显示一个标识线程的吐司.这两个线程具有不同的名称.我以为可能是因为某些原因在调用线程上调用了回调,但是似乎并非如此.那么这里的线程是怎么回事?

解决方法

这里的问题似乎是一个晦涩的线程问题,它在我的原始帖子中看不到,因为我没有发布足够的通话记录来查看.我会解释我在这里找到的情况,以防其影响别人.

导致我问题的完整通话历史记录如下:

>启动Le Scan
>查找我关心的设备
>连接到设备的GATT服务器(返回一个GATT客户端,并且为所有异步通信呼叫提供一个BluetoothGattCallback)
>告诉GATT客户端发现服务()
>稍后,BLE系统调用我的回调函数onServicesdiscovered()
>现在我准备好开始阅读特征,因为服务数据被加载,所以这是我在原始帖子中调用doRead()方法的地方
>告诉GATT客户端读取特征()
>去睡觉,直到阅读完成
—-这是死锁发生的地方,但它应该是:
稍后,BLE系统调用我的callbacck的onCharacteristicRead()
>通知所有等待线程
>返回步骤7并重复

一个错误

本来我的onServicesdiscovered()方法看起来像这样:

public void onServicesdiscovered(final BluetoothGatt gatt,int status) {
    doRead();
}

当doRead()执行时,它将进入休眠状态,从而阻止执行.这样可以防止回调方法的完成,并且显然对整个BLE通信系统进行了加油.

第二个错误

一旦我意识到上述问题,我改变了以下方法

public void onServicesdiscovered(final BluetoothGatt gatt,int status) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            doRead();
        }
    ).start();
}

据我所知,上述版本的方法应该可以工作.我正在创建一个新的线程来运行doRead(),所以睡在doRead()不应该对BLE线程有任何影响.但它确实!这种变化没有影响.

———–编辑笔记————–

发布后,我真的无法理解为什么上述匿名线程不起作用.所以我再试一次,这一次确实有效.不知道第一次出了什么问题,也许我忘了在线程或某事上调用start()

———结束编辑注————

解决方案:

最后,当我的类被实例化(而不是在onServicesdiscovered())上创建一个匿名Thread时,我决定创建一个后台HandlerThread.现在的方法如下所示:

public void onServicesdiscovered(final BluetoothGatt gatt,int status) {
    mBackgroundHandler.post(new Runnable() {
        @Override
        public void run() {
            doRead();
        }
    ).start();
}

以上版本的方法有效.调用doRead()成功地遍历每个特征,因为前一个被读取.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...