准备材料

AndroidStudio

谷歌android-serialport-api

前情提要

网上提供很多基于c语言对安卓串口开发,有jni、cmake等等,不过都太高深,谷歌提供的api已经可以满足基本读写(对数据位、停止位、校验位无要求,默认N81),这也是最简单的串口开发。

Java并不是直接调用c中的函数去和串口交互,而是用cmake或jni编译c得到的so库文件实现的,所以使用谷歌api不用再去把他的c文件之类的拿来,只用把他的so库文件拿来用即可,也不用知道so文件怎么用,谷歌demo中写好了直接调用so文件的java类,所以最终我们只需要导入需要的东西然后在谷歌串口类之上编写就行了。

开始骚操作

  1. 首先解压谷歌api demo放一边备用;
  2. 新建AS项目,一路next,拿到一个空空的自带界面的项目;
  3. 打开项目目录app下的build.gradle,在buildTypes同级设置so文件的lib位置,这里用的自己生成的libs文件夹
android {

    compileSdkVersion 28

    defaultConfig {

        applicationId "com.example.hp.demo"

        minSdkVersion 19

        targetSdkVersion 28

        versionCode 1

        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }

    }

    sourceSets.main{

        jniLibs.srcDirs = ['libs']

    }

}

  

  1. 打开谷歌api对应的lib文件夹android-serialport-api\android-serialport-api\project\libs,将里面的三种CPU架构用的so文件夹全复制过去
  2. 打开谷歌api的源代码目录android-serialport-api\android-serialport-api\project\src,内含谷歌api串口开发地基,将该文件夹android_serialport_api直接复制到自己项目java文件夹内(和com同级)
  3. android_serialport_api这个文件夹包含三件物品:

sample:谷歌api DEMO所用演示代码,移植到自己项目后直接删除,不然会和xml接不上报错

SerialPort.java:我们直接接触的对串口开发操作的类,串口读写都基于此,由该文件和so文件对接,我们的操作和该文件对接

SerialPortFinder.java:一般用不到(我没用到),可以找到并输出所有可用串口名和路径,可能是用于对串口批量操作的,一两个串口的用不到

  1. 在此再次说一下:正常大神操作是,先写c文件和h文件,然后jni或cmake编译得出so文件,然后写调用so文件的java类,然后再调用该java类进行各种操作;

我们的操作是上述操作的最后一步,直接用谷歌大佬写好的c编译好的so写好的java类,在这之上写我们自己的操作

  1. 这时就已经可以准备自己的操作了,在此之前检查几个地方:

1)第3点是否写好

2)SerialPort.java中的末尾有这么一段代码:

static {

System.loadLibrary("serial_port");

}

  

这就是传说中调用so库的地方,第三点没写好是找不到这个库的,此外(“”)中的库名也要和so文件对应,即so文件的libserial_port.so去掉开头lib就是库名

  1. 我们的骚操作刚刚开始:

1) 写一个基于SerialPort.java封装好的串口类,虽然已经可以直接用SerialPort.java,但是SerialPort.java中的方法还是稍微有点基层,当项目里有对多个串口进行不同的操作时这一步是必要的,不然代码太重复繁琐,封装的串口类应该有这几个功能:

从外部设置串口号、波特率

向外部传递串口返回报文

打开串口,获取输入输出流

关闭串口,关闭输入输出流

向串口写入字节*

向串口写入字节数组*

向串口写入字符串*

实时监听串口,获取完整的报文

具体代码见Demo

2) 使用串口类,new一个你做的串口类,注册好串口类的数据接收器,在需要串口发送数据的地方调用串口类的发送方法,在接收器中做好对报文的校验等处理

踩坑预警

  1. 串口返回报文残缺,中间少那么一两个字节

因为你注册了两个对同一个串口的监听器,他俩在互抢

  1. 串口返回报文从中间断开

串口另一头发送的时候可能是一个字节一个字节发送的,或者一段一段发送的,不过都会在很短的时间全给你发过来,这时候最保险的做法就是收到数据时,睡上10~100ms,再读一次(接收数据实际上是你从对串口的输入流缓冲区中取出数据),然后拼上返回给外部

  1. New一个串口太吃资源

接收数据的地方其实是一个循环读取的线程,读取一次让它睡10~100ms再循环

  1. 关闭串口之后该串口读取线程还在执行

把读取线程run()里的内容拿while(){ }括起来,while条件里扔一个布尔型,默认符合条件,关闭串口时改了变量让while不符合条件,线程就自然销毁了

  1. SerialPort.java类new的时候除了串口文件和波特率之外,还要一个int型flags参数

这个我也没搞明白,学长用的时候都是写死了0传过去,没发现出问题

  1. 读取数据时inputStream.read() 方法

该方法返回值是个int,表示读到的字节数组长度,所以读的时候拿个int接着,当读完缓冲区的数据后会返回-1,所以读了之后有无数据都有返回值,所以对返回数据进一步操作前用个if括起来,int大于0再执行;

该方法传递参数有几种不同形式:

1) 传入一个byte[]容器,读到的数据存入该容器,注意不要空指针,不要超出容器容量

2) 传入一个byte[]容器,一个int型起始位置off,一个int型数据长度len,off表示读到的数据从容器的byte[off]位置开始存,len表示读len个字节存进容器,这种传参在第二次读取拼接第一次报文的地方会用到

安卓基于谷歌串口api进行串口开发的更多相关文章

  1. js基于谷歌地图API绘制可编辑圆形与多边形

    之前的工作中需要在谷歌地图上绘制可编辑多边形区域,所以基于谷歌地图API封装了个html页面,通过调用js绘制多边形并返回各点的经纬度坐标:当然首先你要保证你的电脑可以打开谷歌地图... 新建一个ht ...

  2. MSComm控件与Win32 API操作串口有何区别?

    MSComm控件与Win32 API操作串口有何区别? [问题点数:50分,结帖人shell_shell]   收藏帖子 回复 我是一个小兵,在战场上拼命!   结帖率 83.33% 我以前用MSCo ...

  3. 自己编写的基于VC++6.0的串口调试软件,并贡献源程序!

    自己编写的基于VC++6.0的串口调试软件源程序! 程序下载链接: 点击打开链接

  4. 基于微博LBS API开发的周边美图android app

    [app 不完善,就差api了] 几年之前看到过新浪微博开放API中有基于Place的API,授权后可以查看基于地理位置的一些数据,比如某个地点周边的微博动态.某个具体用户的位置动态等等.最近空余时间 ...

  5. 使用Windows API进行串口编程

    使用Windows API进行串口编程   串口通信一般分为四大步:打开串口->配置串口->读写串口->关闭串口,还可以在串口上监听读写等事件.1.打开和关闭串口Windows中串口 ...

  6. 谷歌地图 API 开发之添加标记(解析以及补充)

    今天又看了下官网,发现官网上有地图标记的详细说明.当时居然眼瞎看不见,还琢磨了好久...#$%^&,一定是项目太急,没看到(^o^)/~地址:https://developers.google ...

  7. 谷歌地图 API 开发之获取坐标以及街道详情

    自己的项目中有获取当前点击的坐标经纬度或者获取当前街道的信息的需求.估计这个对于新手来说,还是比较麻烦的,因为从官网上找这个也并不是很好找,要找好久的,运气好的可能会一下子找到. 献上自己写的测试案例 ...

  8. 记录开发基于百度地图API实现在地图上绘制轨迹并拾取轨迹对应经纬度的工具说明

    前言: 最近一直在做数据可视化方面的工作,其中平面可视化没什么难度,毕竟已经有很多成熟的可供使用的框架,比如百度的echart.js,highcharts.js等.还有就是3D可视化了,整体来说难度也 ...

  9. 基于Arduino和python的串口通信和上位机控制

    引言 经常的时候我们要实现两个代码之间的通信,比如说两个不同不同人写的代码要对接,例如将python指令控制Arduino控件的开关,此处使用串口通信是非常方便的,下面笔者将结合自己踩过的坑来讲述下自 ...

随机推荐

  1. Java的强引用、软引用、弱引用、虚引用

    背景 工程中用到guava的本地缓存.它底层实现和API接口上使用了强引用.软引用.弱引用.所以温故知新下,也夯实下基础. 预备知识 先来看下GC日志每个字段的含义 Young GC示例解释 [GC ...

  2. 差分进化算法介绍及matlab实现

    引言 差分进化算法是基于群体智能理论的优化算法,是通过群体内个体间的合作与竞争而产生的智能优化搜索算法,它保留了基于种群的全局搜索策略,采用实数编码.基于差分的简单变异操作和"一对一&quo ...

  3. Linux(centos6.8)配置Mysql环境

    1.下载mysql安装包 https://downloads.mysql.com/archives/community/ 2.查询mysql信息 [1]查询mysql是否已经安装 [root@plut ...

  4. mac 快键键图标对应

    Mac 键盘快捷键 您可以按下某些组合键来实现通常需要鼠标.触控板或其他输入设备才能完成的操作.   要使用键盘快捷键,请按住一个或多个修饰键,然后按快捷键的最后一个键.例如,要使用 Command- ...

  5. laravel 验证器使用

    1.前后端不分离 (form表单提交) 控制器定义验证规则 <?php namespace App\Http\Controllers\Admin; use Illuminate\Http\Req ...

  6. 这行代码告诉你!为什么你地下城与勇士(DNF)的装备强化老是失败?

    模拟地下城与勇士(DNF)的装备强化 tip1: DNF装备强化在+1-+3 不会失败: +4-+7,失败后物品原有强化等级降低1级: +8-+10,失败后掉3级: 10上11或以上就爆了. tip2 ...

  7. MathType如何打出带圆圈的点

    学习了圆的知识后,知道可以用带圆圈的点表示圆,比如"⊙O"表示圆O,即圆心为O的圆.那么要怎么在MathType中打出带圆圈的点? 方法一.直接在工具栏上选择输入 打开MathTy ...

  8. exgcd 学习笔记

    最大公约数 更相减损术:\(\gcd(x,y)=\gcd(x,y-x)(x\leq y)\). 证明: 设 \(\gcd(x,y)=k\),则 \(x=kp,y=kq,\gcd(p,q)=1\). 那 ...

  9. 【mq读书笔记】mq消息消费

    消息消费以组的的模式开展: 一个消费组内可以包含多个消费者,每一个消费组可订阅多个主题: 消费组之间有集群模式与广播模式两种消费模式:集群模式-主题下的同一条消息只允许被其中一个消费者消费.广播模式- ...

  10. 【译】理解Rust中的局部移动

    原文标题:Understanding Partial Moves in Rust 原文链接:https://whileydave.com/2020/11/30/understanding-partia ...