Skip to content

Repository files navigation

YSerialPort

源Android-SerialPort-API,重新封装代码,实现读取串口数据,实现重新组包一次性读取完整数据。可连续读取任意长度数据。

重写串口so库名称和调用函数名称,不与其他串口工具形成so冲突或者类名冲突。

已经多次长时间测试:串口打印机,PLC通信,串口电子秤,串口条码读卡器,串口二维码读卡器,串口LED屏,串口NFC读卡器,读M1区一次性读取64个扇区,读CPU区一次读取16KB数据。

理论上兼容 安卓4.4~安卓14.0

2.2.7之后版本最低支撑安卓4.4(api19)

platformGradlelast commitrepo sizeandroid studiomaven

releases里面有APK文件。点击前往

releases里面有AAR包。点击前往

如果拉取整个项目,请用最新AS(AS2024.3.2以上)打开

不建议直接拉取项目编译,请仔细看完

Gradle采用java17

设置方法: Project Structure ----> SDK Location ----> JDK location was moved to Gradle Settings. ----> Gradle JDK ----> JDK17

已经从jitpack.io仓库移动至maven中央仓库

引用

dependencies {
//更新地址 https://github.com/yutils/YSerialPort 建议过几天访问看下有没有新版本
implementation 'com.kotlinx:yserialport:2.2.8'
}

注:如果引用失败,看下面方案

allprojects {
repositories {
google()
//mavenCentral()
//如果还是不容易拉取,可以试试直接用maven.org
maven { url 'https://repo1.maven.org/maven2' }
}

使用方法

可以参考SendActivity.java

基础使用方法

YSerialPortySerialPort=newYSerialPort(this,"/dev/ttyS4","9600");
//设置数据监听ySerialPort.addDataListener(newDataListener(){
@Overridepublicvoidvalue(StringhexString,byte[]bytes){
//结果回调:haxString , bytes
}
});
ySerialPort.start();

扩展使用方法

java

同步

//拿流用法,自己通过流收发数据SerialPortserialPort = SerialPort.newBuilder(newFile("/dev/ttyS4"), 9600)
.parity(0) // 校验位;0:无校验位(NONE,默认);1:奇校验位(ODD);2:偶校验位(EVEN)
.dataBits(8) // 数据位,默认8;可选值为5~8
.stopBits(1) // 停止位,默认1;1:1位停止位;2:2位停止位
.build();
serialPort.getInputStream();//获取输入流serialPort.getOutputStream();//获取输出流serialPort.tryClose();//关闭//同步收发 (不用每次都创建serialPort对象)SerialPortserialPort=SerialPort.newBuilder(newFile("/dev/ttyS4"),9600).build();
byte[] bytes=YSerialPort.sendSyncOnce(serialPort,bys,1000);
byte[] bytes=YSerialPort.sendSyncTime(serialPort,bys,20,1000);
byte[] bytes=YSerialPort.sendSyncLength(serialPort,bys,20,1000);
serialPort.tryClose();//关闭//发送并等待返回,死等byte[] bytes=YSerialPort.sendSyncOnce("/dev/ttyS4","9600",bytes);
//发送并等待返回,直到超时,如果超时则向上抛异常byte[] bytes=YSerialPort.sendSyncOnce("/dev/ttyS4","9600",bytes,500);
//一直不停组包,(maxGroupTime每次组包时间)当在maxGroupTime时间内没有数据,就返回并关闭连接byte[] bytes=YSerialPort.sendSyncTime("/dev/ttyS4","9600",bytes,500);
//一直不停组包,(maxGroupTime每次组包时间)当在maxGroupTime时间内没有数据,就返回并关闭连接(如果一直有数据,最多接收时间为maxTime)byte[] bytes=YSerialPort.sendSyncTime("/dev/ttyS4","9600",bytes,500,3000);
//一直不停组包,当数据长度达到minLength或超时,返回并关闭连接byte[] bytes=YSerialPort.sendSyncLength("/dev/ttyS4","9600",bytes,500,3000);

异步

//String[] device = YSerialPort.getDevices();//获取串口列表//String[] baudRate = YSerialPort.getBaudRates();//获取波特率列表//YSerialPort.saveDevice(getApplication(), "/dev/ttyS4");//设置默认串口,可以不设置//String device=YSerialPort.readDevice(getApplication());//获取上面设置的串口//YSerialPort.saveBaudRate(getApplication(), "9600");//设置默认波特率,可以不设置//String baudRate=YSerialPort.readBaudRate(getApplication());//获取上面设置的波特率//异步收发YSerialPortySerialPort=newYSerialPort(this,"/dev/ttyS4","9600");
//设置数据监听ySerialPort.addDataListener(newDataListener(){
@Overridepublicvoidvalue(StringhexString,byte[]bytes){
//结果回调:haxString , bytes
}
});
//设置回调线程为主线程,默认主线程ySerialPort.setThreadMode(ThreadMode.MAIN);
//设置自动组包,每次组包时长为40毫秒,如果40毫秒读取不到数据则返回结果ySerialPort.setToAuto(); //ySerialPort.setToAuto(40);//或者,设置手动组包,读取长度100,超时时间为50毫秒。如果读取到数据大于等于100立即返回,否则直到读取到超时为止//ySerialPort.setToManual(100,50);//启动ySerialPort.start();
//发送文字ySerialPort.send("你好".getBytes(Charset.forName("GB18030")));
//退出页面时候注销@OverrideprotectedvoidonDestroy(){
super.onDestroy();
ySerialPort.onDestroy();
}
//如果要自己解析inputStream,请在start()之前实现此方法ySerialPort.setInputStreamReadListener(inputStream->{
intcount=0;
while(count==0)
count=inputStream.available();
byte[]bytes=newbyte[count];
//readCount,已经成功读取的字节的个数,这儿需读取count个数据,不够则循环读取,如果采用inputStream.read(bytes);可能读不完intreadCount=0;
while(readCount<count)
readCount+=inputStream.read(bytes,readCount,count-readCount);
returnbytes;
});

kotlin

//创建对象val ySerialPort =YSerialPort(this, "/dev/ttyS4", "9600")
//设置数据监听
ySerialPort.addDataListener { hexString, bytes ->//结果回调:haxString , bytes
}
//设置自动组包,每次组包时长为40毫秒,如果40毫秒读取不到数据则返回结果
ySerialPort.setToAuto() //ySerialPort.setToAuto(40)//或者,设置手动组包,读取长度100,超时时间为50毫秒。如果读取到数据大于等于100立即返回,否则直到读取到超时为止//ySerialPort.setToManual(100,50)//启动
ySerialPort.start()
//发送文字
ySerialPort.send("你好".toByteArray(Charset.forName("GB18030")))
//退出页面时候注销overridefunonDestroy() {
super.onDestroy()
ySerialPort.onDestroy()
}

代码混淆

-keepclasseswithmembernames class * {
native <methods>;
}
#-keep class com.yujing.** { *; }
-keep class com.yujing.serialport.* { *; }
-keep class com.yujing.yserialport.* { *; }

根据协议头组包完整示例

//原理就是准备一个字符串,每次都数据都拼接到后面,然后判断协议头是否正确?(对了就取对应长度数据然后剪掉用过的数据长度):(如果不对就剪掉协议头数据,重新开始)classTest {
var ySerialPort:YSerialPort?=null//logvar showLog =false//最后一次组包剩余数据privatevar oldSurplus =""funtest() {
ySerialPort =YSerialPort(context, "/dev/ttyS2", "9600")
ySerialPort?.addDataListener { hexString, bytes ->
dataFilter(hexString)
}
ySerialPort?.start()
}
//拆包组包,举例:数据包:02 2B 30 30 30 30 30 30 30 31 42 03 //其中:协议头 02 2B正2D负 6位重量 1位小数点位数 2位校验(2B到30) 03结束位
@Synchronized
fundataFilter(hexStr:String) {
//先组装上一次剩余数据
oldSurplus += hexStr.replace("", "")
if (oldSurplus.isEmpty()) return//定义一个包长度var dataLength =24//判断长度if (oldSurplus.length < dataLength) {
if (showLog) YLog.d("数据长度不够,等一手!$oldSurplus")
return
}
//验证协议头,非02开头就抛弃if (oldSurplus.substring(0, 2) !="02") {
if (showLog) YLog.d("数据异常,抛弃数据头!$oldSurplus")
//剪掉数据头,如果剩余数据大于一个完整包,递归一次
oldSurplus = oldSurplus.substring(2)
if (oldSurplus.length >= dataLength)
dataFilter("")
return
}
//如果有数据长度位,获取长度位+包头+包尾=包长,dataLength重新赋值新的包长//dataLength=数据长度+包头+包尾//验证协议尾,同上//验证校验码//......//获取数据处理 【这儿就是一个完整的数据包!】 【这儿就是一个完整的数据包!】 【这儿就是一个完整的数据包!】 
handle(YConvert.hexStringToByte(oldSurplus.substring(0, dataLength)))
//剪去用过的数据
oldSurplus = oldSurplus.substring(dataLength)
//剩余数据可能还能有完整包。所以递归一次if (oldSurplus.length >= dataLength)
dataFilter("")
}
//处理数据。dataByteArray的长度应该是8privatefunhandle(dataByteArray:ByteArray) {
//处理分析,转换成对象obj//.....//通知前端//YBusUtil.post("某某设备发送的数据", obj)
}
//退出页面时候注销funonDestroy() {
ySerialPort?.onDestroy()
}
}

串口文件位置:/proc/tty/drivers

感谢:Android-SerialPort-API

不懂的问我QQ:3373217 (别问为啥手机没串口,别问模拟器怎么调试串口(可以映射),别问USB转的串口为什么不能识别)

如果是USB转串口,请参考这个工程:

CH340/CH341的USB转串口

About

安卓串口通信app,实现读取串口数据,实现重新组包一次性读取完整数据。可连续读取任意长度数据。APK在releases里面。觉着不错的话可以 Start 一下哟!

Resources

Stars

217 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages