解决安卓蓝牙快传大量数据出现部分数据丢失问题

最近自己做一个计步器,需要从从机(arduino uno + mpu6050 + hc-05)接收数据,每一秒钟接收20组长度为20字节左右的数据,在串口上观察数据输出结果正常,如图1:

但是当利用蓝牙传数据的时候,上位机端(安卓手机客户端)就会出现数据丢失的问题,如图:

可以发现,这个数据丢的特别严重,既然串口上面输出的结果是正确的,那么证明单片机本身没有任何问题。我把目光转移到了蓝牙模块上。蓝牙模块hc-05,支持蓝牙v2.0,传输速率大约在1.8M/s---2.1M/s,所以一秒传我那最多400字节的数据没有任何压力(这个排除法我可是做了整整2天啊。。。还和网友通宵交流。。。没办法遇到难题还能怎么半呢,还是得自己想法子解决,不要想着别人可以帮你解决)。那么问题出在哪里呢?还有最后一个可以怀疑得目标,上位机!

上位机上得蓝牙代码用得是google官方demo,然后demo里面接收数据是这么写的:

<span style="font-size:18px;">public void run() {//接收数据的线程

            byte[] buffer = new byte[1024];
            int bytes;
            // Keep listening to the InputStream while connected
            while (true) {
                try {
                    bytes = mmInStream.read(buffer);
                    mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer).sendToTarget();

                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionLost();
                    break;
                }
            }
        }</span>

然后handler的处理是这么写的:
case MESSAGE_READ://3读取数据

                  byte[] readBuf = (byte[]) msg.obj;
                  recieveStr = new String(readBuf, 0, msg.arg1);//得到数据字符串
                  Log.e("Length",String.valueOf(recieveStr.length()) + "  " + recieveStr);
<span style="white-space:pre">		</span>  break;

然后结果就有了上面的那一幕,数据丢了!

我苦思冥想,觉得官方的demo毕竟是google神牛写的啊,99%都没啥问题的呀(1%留给自己来质疑),然后我就一行代码一行代码的排除,然后就发现handler消息传递有两种方法,一种就是上面代码里面给出来的obtainMessage()方法,另外一种就是sendMessage()方法,然后这两种方法有什么区别呢,大家可以先看看这个解释详细的:传送门1,传送门2

其实就是一个new与不new,导致的效率不同的区别,obtainMessage()因为是直接从message global pools里面取出的一个新的message实例,所以在快传大量数据的过程中,MessageQueue大小有限,如果消息处理不及时,而又有新的数据写入,有可能造成message被覆盖,也就出现了上面的数据丢失现象。虽然android推荐使用obtainMessage(),有其利但是也有其弊。

于是我就尝试用sendMessage()来解决问题:

  public void run() {

            byte[] buffer = new byte[1024];
            int bytes;
            String readMessage;
            // Keep listening to the InputStream while connected
            while (true) {
                try {
                    int availableBytes = mmInStream.available();
                    if (availableBytes > 0) {
                        bytes = mmInStream.read(buffer);
                        Message msg = new Message();
                        Bundle data = new Bundle();
                        readMessage = new String(buffer,0,bytes);
                        data.putString("BTdata",readMessage);
                        msg.what = MainActivity.MESSAGE_READ;
                        msg.setData(data);
                        mHandler.sendMessage(msg);
                    }


                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionLost();
                    break;
                }
            }
        }

handler处理:

 case MESSAGE_READ://3读取数据

            
                    Bundle data = msg.getData();
                    recieveStr = data.getString("BTdata");
                   Log.e("Length",String.valueOf(recieveStr.length()) + "  " + recieveStr);

                    writeFile(recieveStr);//把收到的数据写到文件里面
                    break;

看看运行结果:


非常好,解决了数据丢失的问题。虽然这样做牺牲了部分效率,但是相比丢数据这种危险的事情,这是非常非常值得的。

上文如果有错误的地方,请各位指正!微笑



  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
《Android高级编程》首先简要介绍Android软件栈,接着陈述为手机创建稳定可靠、赏心悦目的应用程序的基本原理。通过学习,您可以打下牢固的理论根基,了解使用当前Android 1.0 SDK编写定制移动程序所需的知识,还能灵活快捷地运用未来的增强功能构建最前沿的解决方案。   Android提供一个开放的开发环境,为针对移动设备编写创新应用程序带来了激动人心的新机遇。作为使用AndroidSDK构建这些应用程序的实用指南书籍,《Android高级编程》从始至终穿插了一系列示例项目,每个项目都引入Android的新功能和新技术,以助您达到最圆满的学习效果。书中介绍Android的所有基本功能,并通过简明扼要的示例引导您使用高级功能。 更多关于安卓软件系统详情-安卓风 目录: 第1章 Android简介 1.1 一些背景信息 1.1.1 不远的过去 1.1.2 未来的前景 1.2 对Android的误解 1.3 开放的移动开发平台 1.4 自带的Android应用程序 1.5 Android SDK功能 1.5.1 对包括摄像、GPS和加速计在内的硬件的访问 1.5.2 自带的Google地图、地理编码和基于位置的服务 1.5.3 后台服务 1.5.4 SQLite数据存储和检索数据库 1.5.5 共享数据和应用程序间通信 1.5.6 使用Google Talk的P2P服务 1.5.7 扩展的数据支持和2D/3D图形 1.5.8 优化的内存和进程管理 1.6 开放手机联盟简介 1.7 运行Android的环境 1.8 从事Android开发的原因 1.8.1 推动Android普及的因素 1.8.2 Android的独到之处 1.8.3 改变移动开发格局 1.9 开发框架简介 1.9.1 开发包中的资源 1.9.2 理解Android软件栈 1.9.3 Dalvik虚拟机 1.9.4 Android应用程序架构 1.9.5 Android库 1.9.6 高级Android库 1.10 小结 第2章 开始入手 2.1 Android开发 2.1.1 开始前的准备工作 2.1.2 创建第一个Android活动 2.1.3 Android应用程序的类型 2.2 面向移动设备的开发 2.2.1 关于硬件设计的考虑事项 2.2.2 考虑用户环境 2.2.3 Android开发 2.3 To-Do List示例 2.4 Android开发工具 2.4.1 Android模拟器 2.4.2 Dalvik调试监控服务(DDMS) 2.4.3 Android调试桥(ADB) 2.5 小结 第3章 创建应用程序和活动 3.1 Android应用程序的组成部分 3.2 程序清单简介 3.3 使用清单编辑器 3.4 Android应用程序生命周期 3.5 理解应用程序的优先级和进程状态 3.6 分离资源 3.6.1 创建资源 3.6.2 使用资源 3.6.3 To-DoList资源示例 3.6.4 为不同的语言和硬件创建资源 3.6.5 运行时配置更改 3.7 深入探讨Android活动 3.7.1 创建一个活动 3.7.2 活动生命周期 3.7.3 Android活动类 3.8 小结 第4章 创建用户界面 4.1 Android UI基本设计 4.2 View简介 4.2.1 使用View创建Activity(活动)用户界面 4.2.2 Android Widget工具箱 4.3 布局简介 4.4 创建新的View 4.4.1 修改现有的View 4.4.2 创建复合控件 4.4.3 创建定制的Widget和控件 4.4.4 使用定制的控件 4.5 创建和使用菜单 4.5.1 Android菜单系统简介 4.5.2 定义活动的菜单 4.5.3 动态更新菜单项 4.5.4 处理菜单选择 4.5.5 子菜单和上下文菜单 4.5.6 To-Do List示例续 4.6 小结 第5章 Intent、广播接收器、 Adapter和Internet 5.1 Intent简介 5.1.1 使用Intent来启动活动 5.1.2 使用Intent Filter来为隐式Intent提供服务 5.1.3 使用Intent Filter作为插件和扩展 5.1.4 使用Intent来广播事件 5.2 Adapter简介 5.2.1 Android提供的部分Adapter简介 5.2.2 使用Adapter绑定数据 5.3 使用Internet资源 5.3.1 连接到Internet资源 5.3.2 利用Internet资源 5.4 Dialog简介 5.4.1 Dialog类简介 5.4.2 使用活动作为对话框 5.5 创建一个地震查看器 5.6 小结
Android蓝牙配对传输数据协议Demo是一个示例应用程序,用于演示在Android设备之间进行蓝牙配对传输数据的协议。该Demo应用程序旨在帮助开发人员理解和学习蓝牙配对传输数据的原理和实现方式。 该Demo应用程序包含以下几个主要部分: 1. 设备配对:该部分演示如何在两个Android设备之间建立蓝牙连接并进行配对。用户可以在应用程序中选择要配对的设备,然后触发配对过程。在配对成功后,两台设备将建立蓝牙连接。 2. 数据传输:该部分演示如何在已配对的蓝牙设备之间传输数据。用户可以在应用程序中选择要传输的数据,然后触发数据传输过程。传输的数据可以是文本、图片或其他类型的文件。在数据传输过程中,应用程序将通过蓝牙连接将数据发送到另一台设备。 3. 数据接收:该部分演示如何在已配对的蓝牙设备上接收传输的数据。用户可以在应用程序中查看接收到的数据,并进行相应的处理。接收到的数据可以是文本、图片或其他类型的文件。 通过这个Demo应用程序,开发人员可以学习如何使用Android的蓝牙API来实现设备配对和数据传输功能。他们可以了解到蓝牙配对的步骤和过程,以及如何处理传输数据。这个Demo为开发人员提供了一个基础的示例,可以在其基础上进行二次开发和定制,以满足特定应用场景的需求。 总之,Android蓝牙配对传输数据协议Demo是一个有助于学习和理解蓝牙配对传输数据原理和实现方式的示例应用程序。通过该Demo,开发人员可以快速上手并开发出适用于他们应用场景的蓝牙配对传输数据功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值