最近的android蓝牙开发项目也逐渐接近尾声,基本的功能都已经完成,只剩下界面的设计。现在真的是舒了一口气!

作为编程学习经验只有1年的菜鸟,这是我独自完成的商业性产品,而且还是涉及到与单片机蓝牙模块的底层通信,难度自然不小。最大的难度不是知识点不懂,而是调试,因为干扰因素实在是太多,很难找出是软件的问题还是硬件的问题,所以,在代码中一定要设置好调试点,以方便查询问题的症结点。

线程也是一个考虑的因素。凡是涉及到I/O的编程,都是一个不小的难题,因为它里面会涉及到线程问题。java的线程库的确非常方便好用,但要想正确的使用还是一个值得研究的话题,最坏的情况就是我们胡乱的使用线程技巧结果导致无谓的线程开销。

当然,这里的线程还是非常简单,关于同步,锁机制这些高级的话题根本没有用到,基本的线程知识就已经够用了。

与蓝牙模块通信最重要的地方就是数据的发送和接收,因为是底层的操作,所以更多是发送16进制数据。

进制转换是我们程序员的必修课,属于基本素质。这里需要的是将字节数组转化为16进制字符串,方法都是通用的:

 public static String bytesToHexString(byte[] bytes) {
String result = "";
for (int i = 0; i < bytes.length; i++) {
String hexString = Integer.toHexString(bytes[i] & 0xFF);
if (hexString.length() == 1) {
hexString = '0' + hexString;
}
result += hexString.toUpperCase();
}
return result;
}

接下来就是发送数据。

发送数据非常简单,之前有关于蓝牙编程的博文已经讲到了,http://www.cnblogs.com/wenjiang/p/3200138.html,这里只讲重要的一点:大容量字节数组的发送。

我们需要发送64个字节的数组,如果一次性发送过去,单片机那里可能无法及时处理以致没有任何回应,因为单片机那里是设置了数据接收的延时时间。要想畅通的与蓝牙模块通信,考虑这个时间差非常重要。调整字节的发送速率,就成为非常关键的一步。值得注意的是,数据的发送是非常快的,就是因为这样才会导致单片机那里无法及时处理,所以,每次发送后的延时是非常重要的。我们单片机那里的延时是10毫秒,所以我们选择发送完每个字节后就延时10毫秒再发下个字节。

 for (byte b : bytes) {
out.write(b);
Thread.sleep(10);
}

具体的延时时间和字节发送速率得看单片机那里程序的设置。
     在使用InputStream的时候,必须注意,InputStream的读取是阻塞的。这点在一般的情况下是不会影响到我们的程序,但是记住这个情况对于代码的设计是非常重要的,尤其是在考虑用户体验的时候。

无参数的read()是每次只从流中读取一个字节,这种做法效率非常低,但是简单,像是读取整数值这种情况,使用read()就非常好,但如果是16进制字符串呢?使用InputStream.read(byte[] b)或者InputStream.read(byte[] b,int off,int len)方法,这样一次就能读取多个字节。

如果是读取多个字节,我们常常使用InputStream.available()方法来获取数据流中可读字节的个数。读取本地数据的时候,该方法发挥得非常好,但如果是读取非本地数据,就可能出现字节遗漏的问题,像是要读取100个字节,可能就是90个,甚至是0个。

出现0个的情况就是单片机那边没有响应或者字节还没发送过来,这时我们就需要一个循环来保证我们能够拿到数据:

  int count = 0;
while (count == 0) {
count = in.available();
}
byte[] bytes = new byte[count];
in.read(bytes);

但像是上面的90个字节的情况就是字节遗漏。对于这种情况,解决方法也很简单:

  byte[] bytes = new byte[count];
int readCount = 0; // 已经成功读取的字节的个数
while (readCount < count) {
readCount += in.read(bytes, readCount, count - readCount);
}

最好是这么写,因为Java的API已经明确的告诉我们,read()方法并不能保证读取到我们想要的字节数。
      这样我们就能解决16进制数据的发送和读取了。

android 蓝牙编程重点---如何发送和接收16进制数据的更多相关文章

  1. Flex接收51单片机发送过来的16进制数据转换为String

    private static function toHex(bytes:ByteArray):String{ var pos:int =bytes.position; bytes.position=0 ...

  2. Android源码中的FLAG为何使用16进制

    1.在阅读源码的时候经常发现有一些标志属性使用一些位操作来判断是否具有该标志,增加标志或者去除标志. 比如View.java中的 /** * This view does not want keyst ...

  3. delphi的tserversocket控件如何接收16进制数

    http://bbs.csdn.net/topics/390473005 对方客户端发送数据如:68 00 00··········:接收完成后,数据长度没错(13),但是显示接收结果时,只显示一个字 ...

  4. Android选择/拍照 剪裁 base64/16进制/byte上传图片+PHP接收图片

    转载请注明出处:http://blog.csdn.net/iwanghang/article/details/65633129认为博文实用,请点赞,请评论,请关注.谢谢! ~ 老规矩,先上GIF动态图 ...

  5. C# Socket发送接收字节数组和十六16进制之间转换函数

    近期在使用远程网络模块的时候, 需要用的Socket发送数据,远程模块指令为16进制. 官方提供的DEMO比较繁琐.不方便新手使用. 下面的转换函数可大大方便新手使用. // 16进制字符串转字节数组 ...

  6. pyserial 16进制显示与发送

    pyserial 16进制显示与发送 http://www.centoscn.com/python/2013/0817/1320.html 十六进制显示的实质是把接收到的字符诸葛转换成其对应的ASCI ...

  7. QT 串口通信 数据16进制发送

    在QT中进行串口通信时,很多情况要用到发送16进制的数据.从网上找来了一段代码测试能用: static QByteArray QString2Hex(QString str) { QByteArray ...

  8. C# 发送16进制串口数据

    一个困扰两天的问题:需要通过串口向设备发送的数据:0A010 7e 08 00 11 00 00 7e 76 7f我先将每个16进制字符转换成10进制,再将其转换成ASCII码对应的字符. /// & ...

  9. C#把汉字转换成16进制(HEX)并向串口发送数据

    报警器实例:(有发送,无返回获取) using System; using System.Collections.Generic; using System.Linq; using System.Te ...

随机推荐

  1. ivr

    /************************************************************* 北京高阳圣思园信息技术有限公司IVR业务: 流程说明:公司介绍子流程 发布 ...

  2. Android基础(五) Service全解析----看不见的Activity

    一.服务的介绍: 作为Android四大组件之中的一个,Service(服务)也常常运用于我们的日常使用中,它与Activity的差别在于:Service一直在后台执行.没实用户界面.所以绝不会到前台 ...

  3. Apache Rewrite规则详解

    参考链接:http://slj.me/2009/04/apache-rewrite-regular/ 1.Rewrite规则简介 Rewirte主要的功能就是实现URL的跳转,它的正则表达式是基于Pe ...

  4. 解决工作中遇到的一个"打开,保存"文件框的bug的过程

    工作中遇到的这个问题还是很有意思的.其中嵌套了很多奇葩性的问题. (转载请指明出于breaksoftware的csdn博客) 我们来看下故事的发生过程,QA同学发现我们存在如下的bug 看到如此多的串 ...

  5. 第八周(1) Word信函与邮件

    第八周(1) Word信函与邮件 教学时间 2013-4-15 教学课时 2 教案序号 13 教学目标 1.学会使用word制作信封和标签2.理解邮件合并的概念和功能3.学会利用邮件合并批量制作文档 ...

  6. Java多线程之Future与FutureTask

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6561154.html  一:Future 在使用实现Callable创建线程时,call()方法是有返回值的. ...

  7. android ndk native错误分析方法

    使用ndk自带的工具进行分析, /mnt/d/Projects/linuxEnv/env/toolchains/aarch64-linux-android-4.9/bin/aarch64-linux- ...

  8. Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node ……

    解决办法是加一个等待时间即可解决问题: setTimeout(function () { you code }, );

  9. java 获取class文件所在路径

      java 获取class文件所在路径 CreateTime--2017年11月14日15:14:32 Author:Marydon 1.获取class文件所在路径(磁盘路径.绝对路径) // 获取 ...

  10. java 文件复制

      java实现文件复制 CreateTime--2017年9月7日15:04:48 Author:Marydon 1.需求 根据原文件复制一份到指定位置 2.代码实现 需要导入: import ja ...