Android 通过低功耗蓝牙接收的信息包处理速度慢的原因是什么?

2023-12-30

任务是将信息从具有 BLE 4.0 的芯片高速(至少 24 kbps)传输到 Android 设备。蓝牙规范允许这样做。我们使用了两种方法:写/读(我们将请求写入一个特征,从另一个特征中读取答案)和通知(芯片以 50 ms 的频率不断发送数据包)。在写入/读取的情况下,重写和读取数据包的时间在 100 ms 左右变化。使用notify时,时间设置为50毫秒,但Android会丢包。相反,他收到了数据包的旧值,或者错过并读取了下一个数据包两次,尽管芯片准确地发送了带有新值的通知。我该如何解决或解决这个问题?

private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
                mConnected = true;
                updateConnectionState(R.string.connected);
                invalidateOptionsMenu();
            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
                mConnected = false;
                updateConnectionState(R.string.disconnected);
                invalidateOptionsMenu();
                clearUI();
            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
                // Show all the supported services and characteristics on the user interface.
                //displayGattServices(mBluetoothLeService.getSupportedGattServices());
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
                stopT =System.currentTimeMillis();
                //double td=stopT-startT;

                time1.add(stopT - startT);
                //double td = Math;
                double sum = 0;
                for(int i =0;i<time1.size();i++) sum+= time1.get(i);
                double td = sum/time1.size();
                TextView textView3 = (TextView) findViewById(R.id.textView3);
                textView3.setText(String.valueOf(td));
                displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));

                //for (int i = 0; i < BluetoothLeService.byteArray.length; i++) time.add(Double.valueOf(BluetoothLeService.byteArray[i]));

                float[] floatArray = new float[BluetoothLeService.byteArray.length];
                for (int i = 0; i < BluetoothLeService.byteArray.length; i++) floatArray[i] = (float)BluetoothLeService.byteArray[i];
                float[] tmp = new float[time2.length + floatArray.length];
                System.arraycopy(time2, 0, tmp, 0, time2.length);
                System.arraycopy(floatArray, 0, tmp, time2.length, floatArray.length);
                time2 = tmp;

                if (cnt1 < 51) {
                    Matr[cnt1]=floatArray;
                    cnt1++;
                }


                if (flag == 1) {
                    startT = System.currentTimeMillis();
                    //mBluetoothLeService.readCustomCharacteristic();
                    mBluetoothLeService.writeCustomCharacteristic(hex);
                }
                if(flag_notify == 1)startT = System.currentTimeMillis();
            } else if (BluetoothLeService.ACTION_CHARACTERISTIC_WRITE.equals(action)) {
                mBluetoothLeService.readCustomCharacteristic();
            }
        }
    };

private void broadcastUpdate(final String action,
                                 final BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);

        // This is special handling for the Heart Rate Measurement profile.  Data parsing is
        // carried out as per profile specifications:
        // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
        if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
            int flag = characteristic.getProperties();
            int format = -1;
            if ((flag & 0x01) != 0) {
                format = BluetoothGattCharacteristic.FORMAT_UINT16;
                Log.d(TAG, "Heart rate format UINT16.");
            } else {
                format = BluetoothGattCharacteristic.FORMAT_UINT8;
                Log.d(TAG, "Heart rate format UINT8.");
            }
            final int heartRate = characteristic.getIntValue(format, 1);
            Log.d(TAG, String.format("Received heart rate: %d", heartRate));
            intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
        } else {
            // For all other profiles, writes the data formatted in HEX.
            final byte[] data = characteristic.getValue();
            byteArray =data;
            if (data != null && data.length > 0) {
                final StringBuilder stringBuilder = new StringBuilder(data.length);
                for(byte byteChar : data)
                    stringBuilder.append(String.format("%02X ", byteChar));
                intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
            }
        }
        sendBroadcast(intent);
    }

蓝牙Gatt回调:

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                //gatt.requestMtu(512);
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server.");
                // Attempts to discover services after successful connection.
                Log.i(TAG, "Attempting to start service discovery:" +
                        mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            } else {
                Log.w(TAG, "onServicesDiscovered received: " + status);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                                          BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_CHARACTERISTIC_WRITE, characteristic);
            } else {
                Log.w(TAG, "onCharacteristicWrite received: " + status);
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }
    };

更新:回调函数的更改。

public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            StopT = System.currentTimeMillis();
            if (cnt1 < kolvo) {
                save[cnt1]=characteristic.getValue();
                td1 [cnt1] = StopT - StartT;
                StartT = System.currentTimeMillis();

                cnt1++;
            }
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 通过低功耗蓝牙接收的信息包处理速度慢的原因是什么? 的相关文章

  • 从数据库中删除项目后如何从 recyclerView 中删除项目

    我正在使用 recyclerView 来显示当用户单击每个项目的删除按钮时可以删除的项目列表 为了做到这一点 我使用了 recyclerview 适配器 我想要的是 从该 recycleView 适配器中 当用户单击某个项目的删除按钮时 会
  • Android Studio Profiler 中显示“无可调试进程”

    当我尝试在 Android Studio 中使用探查器时 我能够看到已连接的设备 但在探查器中收到 无可调试进程 有人可以帮助我为什么我收到 不可调试的进程 吗 您可以尝试以下任意 全部操作 使缓存失效并重新启动Android Studio
  • java中将函数作为参数传递

    我正在熟悉 Android 框架和 Java 并希望创建一个通用的 NetworkHelper 类 该类将处理大部分网络代码 使我能够从中调用网页 我按照developer android com 上的这篇文章创建了我的网络类 http d
  • Dagger 2 不会注入我的对象,但可以从组件中获取

    我有我的组件 GithubListActivityScope Component modules GithubListActivityModule class GlideActivityModule class public interfa
  • 如何访问对话框中的 EditText 字段?

    如何访问对话框中的 EditText 字段 将 EditText 小部件放入对话框中
  • 旋转对话框的自定义主题

    我想自定义当我单击 spinnermode dialog 中的微调器时出现的对话框的外观 我想使用对话框片段 但没有找到文档 是否可以 不会 外观是固定的 给人一种操作系统的感觉 您必须创建自己的微调器才能执行此操作 这并不容易 但如果微调
  • 字符串生成器最大长度

    我想知道字符串生成器 或字符串缓冲区 的最大容量是多少 我的 Android 应用程序中有一个静态变量 它应该保存日志字符串 它最多可以容纳 130 行和大约 10000 个字符 我如果我附加更多内容 但它只是不显示 没有错误 没有例外 所
  • 如何突出显示在 Textview android 中单击的单词

    我正在创建一个应用程序 在其中我从 EditText 中的用户获取输入 现在 单击按钮后 输入的字符串将显示在 TextView 中 现在我的问题是 当用户单击任何单个单词时 我会使该单词在 TextView 中突出显示 例如 用户输入 你
  • 无法创建变体“android-manifest-metadata”

    我在 Playstore 上上传了我的应用程序 bundle aab 方法 它在 android 6 0 上运行正常 没有错误 但在 android 7 0 设备上出现错误 并且无法运行该应用程序 我使用了 Gradle 构建类路径 3 1
  • PinnedHeader Google 加上 GridView?

    背景 Google google 应用程序可以很好地查看 亮点 类别中的图像 对于该屏幕上的每个部分 他们制作了一个标题 其中包含可单击的文本和一个用于选择该部分的所有照片的按钮 对于每个部分 他们还以网格状方式显示照片 它是这样的 这是另
  • Android 时间选择器在分钟滚动时自动更改小时

    例如 当我在 TimePicker 上滚动分钟时 在将分钟滚动到 59 后 小时会自动滚动到 7 因此新时间将为 07 59 同样的方式 如果我有 07 59 并且我将分钟滚动到 00 小时将自动滚动到 8 所以时间将是 08 00 此逻辑
  • Kotlin + Room:java.lang.IllegalArgumentException:void 无法转换为元素

    我试图在我的 Java Kotlin 项目中添加 Room 但是当我尝试编译该项目时 它失败了 app kaptDebugKotlin出现以下错误 e java lang IllegalStateException failed to an
  • 使用 Android Exoplayer 调整 Dash 流音量

    我正在尝试设置一个搜索栏来控制 exoplayer 流式破折号实例的级别 我正在使用的设置是演示项目的修改版本 并且无法确定我应该尝试影响搜索栏输出的哪个元素 即如何正确使用 MSG SET VOLUME 等 任何意见将不胜感激 我正在寻找
  • 免费和付费版本 Android 应用程序的最佳方法?

    我开发了一个 Android 应用程序 我希望它可以作为免费版本和付费版本提供 最好的方法是什么 我可以想到三种解决方案 将项目分成两个分支并维护它们 创建一个库项目并有两个附加项目 一个 免费 版本和一个 付费 版本 使用应用内结算 问
  • 如何在android上使用xamarin表单执行脚本

    我正在尝试在 Android Mono 上使用 Xamarin Forms 运行 C 脚本 当我运行脚本时 我收到错误 System IO FileNotFoundException 找不到文件 mscorlib dll 这是我试图执行的代
  • 加载带有月份标题的 recyclerview 不同类型适配器

    如果从 api 获取不同的月份名称 则尝试将月份名称显示为标题 在这里 我加载月份标题 但是当我加载标题时 它不会加载其他视图 如果数据不同 我需要将月份加载为标题 并且还加载其他视图持有者 我看到一些例子 他们都在 Model 类中使用
  • 如何在flutter上关注android tv应用程序中的列表视图项目

    我想在 flutter 中构建一个 android 电视应用程序 几乎所有事情都已完成 但一个问题是我无法集中注意力 例如一些弹出效果或边框更改任何告诉用户您现在正在使用此项目的内容 我们在列表视图中迭代的项目 我想要在应用程序中看到的图像
  • 具有通用类的自定义 Android 适配器

    我正在尝试在 Android 中创建一个通用适配器 所以我不能一遍又一遍地编写它 问题是 它正在工作 但它的回收效果不是很好 它显示了我想要的内容 但是当我滚动时 它的顺序不同 public class CustomListViewAdap
  • Android Studio-公司域名

    在Android Studio中 当您创建新项目时 系统会提示您输入域名 我已经知道您可以制作一个 但是如果您想在 Google Play 商店上分发您的应用程序怎么办 即使我永远不会使用我的域 我是否需要购买一个网络域来分发我的应用程序
  • 什么是 Android DecorView?

    http developer android com reference android view Window html getDecorView http developer android com reference android

随机推荐

  • 在使用 AngularJS 的 Chrome 应用程序中,我可以直接将 ngSrc 指令用于内部图像吗?

    我正在使用 AngularJS 编写一个 Chrome 应用程序 我知道 当访问外部图像时 您必须执行跨源 XMLHttpRequest 并将它们作为 blob 提供 我有一堆内部图像 本地应用程序资源 它们遵循我想要在 ngRepeat
  • 选择容器后 JProfiler 远程进程列表为空

    我正在使用 JProfiler 12 并尝试通过 SSH 连接到 Docker 容器中的远程 JVM 进程 我已按照此处的说明进行操作 https www ej technologies com products jprofiler wha
  • 仅使用一元绑定语法表达 do 块

    据我所知 doHaskell 中的块只是一元绑定运算符的某种语法糖 例如 可以转换 main do f lt readFile foo txt print f print Finished to main readFile foo txt
  • uitableviewcell 的数据在滚动时相互重叠

    我有一个包含四个部分的表格视图 所有部分都有两个文本字段和一个位于不同行的标签 我添加了一些文本作为文本字段的占位符 最初 数据看起来很好 但是当我滚动表格视图时 单元格开始出现重叠的数据 My Code UITableViewCell t
  • 我如何检查是否已收到 Playwright 的回复?

    使用 Java 我试图等待对我正在等待的 Javascript 脚本之一的响应 我已经发现我可以使用等待响应 https playwright dev java docs api class page page wait for respo
  • React.js 中的 setState 与 refs

    我在反应中创建了选项卡 现在单击我必须更改选项卡的类 选项卡类可能如下 1 active2 上一个活动3 已选择 单击选项卡类后将变为active并在使用前检查是否已选择alreadySelected类和active最后一个活动选项卡中的类
  • 如何将多个 PNG 合并为一个大 PNG 文件?

    我有大约 6000 个 PNG 文件 256 256 像素 并希望将它们组合成一个大 PNG 以编程方式保存所有这些文件 最好 最快的方法是什么 目的是在纸上打印 因此使用某些网络技术不是一种选择 拥有一个单一的图片文件将消除许多使用错误
  • Go 中的 exec.Command() 与环境变量

    我想在 Go 中运行以下代码 out err exec Command echo PATH Output 结果是 PATH 而不是 PATH bin 的预期值 为什么 我怎样才能得到期望值 shell 没有解释您的命令 这就是预期的变量替换
  • {} + "" 与 "" + {} - 加法的一致性 [重复]

    这个问题在这里已经有答案了 前几天我在 Reddit 上偶然发现了这个 海报指出 等于0 而类似的 等于一个空 object Object 正常的数学规则告诉我这很奇怪 但为什么会这样呢 代币 语句的开头可能意味着对象文字的开始 也可能意味
  • 检索 Z3Py 中的值会产生意外结果

    我想找到一个表达式的最大间隔e对所有人来说都是如此x 编写这样的公式的方法应该是 Exists d ForAll x in d d e and ForAll x not in d d e 为了得到这样一个d 公式f在 Z3 中 看上面的 可
  • 从预先输入选择更新模型

    考虑我的正文中的以下内容html file div class container fluid div
  • Data::Dumper 中是否有相当于 Perls 的 Dumper() 方法的 C 语言?

    本质上 我正在寻找的是一个可以让我做这样的事情的函数 转储器 some obj 输出 some objs 的数据结构 Thanks C 不支持任何类型的开箱即用的反射 此外 它不是硬类型 因为一旦将其编译为机器代码 类型就不再存在 与某些高
  • ngrx - 有条件地停止/删除效果/操作

    我目前正在使用 Ionic2 和 ngrx 构建一个应用程序 如果没有网络连接 我会尝试停止某些操作 通过停止 我的意思是以某种方式使它们对其他效果和商店不可见 或阻止它们进一步 传播 有没有办法做这样的事情 Effect checkNet
  • Flutter、原生 Admob、广告加载失败:0

    https pub dev packages google mobile ads https pub dev packages google mobile ads 我复制了这个例子 除了 原生广告 之外 一切正常 当然 MainActivi
  • 如何从 CMSampleBufferRef 获取字节并通过网络发送

    Am 使用 AVFoundation 框架捕获视频 在 Apple 文档的帮助下http developer apple com library ios documentation AudioVideo Conceptual AVFound
  • cocos2d中如何填充纹理?

    我有一个形状和纹理图像 shape png texture png 我想在cocos2d 中将形状绘制为texture png 图案 形状尺寸比纹理图像大得多 因此自动填充整个形状的纹理图案 我试图认识路 找不到 有人有办法解决这个问题吗
  • “不变违规:requireNativeComponent:在 UIManager 中找不到“RNSScreen”。” React Native cli 出错

    我不断收到 RNSScreen 错误 我已遵循反应导航指南上的所有说明 但没有任何效果对我有用 看起来本机包不会自动链接 所以试试这个 Note 你的情况可以是 代替 因为我正在使用 Monorepo Podfile pod RNScree
  • 动态调整 ggplot2 图例的大小以适应 Quarto 中的文档类型

    我正在使用 R 生成包含图形和表格的四开本文档 应渲染此文档以创建 HTML 和 PDF 文件 大部分都工作得很好 然而 我有很多图例的人物 并且在生成情节时 一些图例被切到了侧面 我找到了调整图例大小的解决方案 以便所有图例都适合使用以下
  • 用于 Node.js 插件开发的 CMake 或 gyp

    在大多数教程中 他们使用 gyp 作为 C Node js 附加开发的构建系统 然而 与 gyp 相比 CMake 历史悠久 文档也多得多 因此 我的问题是 哪一个更适合 Node js C 插件开发 谢谢 我今天刚刚发布了我的新模块 CM
  • Android 通过低功耗蓝牙接收的信息包处理速度慢的原因是什么?

    任务是将信息从具有 BLE 4 0 的芯片高速 至少 24 kbps 传输到 Android 设备 蓝牙规范允许这样做 我们使用了两种方法 写 读 我们将请求写入一个特征 从另一个特征中读取答案 和通知 芯片以 50 ms 的频率不断发送数