- 1.添加依赖环境
- 2.实现base接口 这里提供给Fragment
- 3.Device Bean 类
- 4.基于单例的全局串口管理器
- 5.读串口线程
- 6.实现用于通信的消息类
- 6.1 日志消息数据接口
- 6.2 log管理类
- 6.3 收到的日志
- 6.4 发送的日志
- 7.Demo下载
// 串口
implementation 'com.licheedev:android-serialport:2.1.2'
implementation 'com.github.licheedev.CommonSize:common_size_w1080_n1920:1.3.1'
//rx
implementation 'io.reactivex.rxjava2:rxjava:2.2.19'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// eventbus
implementation 'org.greenrobot:eventbus:3.2.0'
// 选文件的
implementation 'ru.bartwell:exfilepicker:2.1'
// 硬件操作工具类
implementation 'com.licheedev:hardwareutils:1.0.0'
implementation 'com.licheedev:logplus:1.0.0'
根据Android官方提供的串口API实现
2.实现base接口 这里提供给Fragment需要将项目整体升级为AndroidX 环境以使用android 官方自带的串口操作接口,法则会报错找不到类,如果不能将项目升级为Android X 环境 可以使用文档底部提供的Demo,里面有底层串口读写的so包包括so对应的c、c++源码,可以根据自己的主板架构自行编译
public class SerialPortFragment extends GlobalFragment {
private Device mDevice;
protected void initSerialPortDevice(){
mDevice = new Device("/dev/ttyS1","115200");
}
protected void switchSerialPort(boolean mOpened) {
if (mOpened) {
SerialPortManager.instance().close();
mOpened = false;
} else {
mOpened = SerialPortManager.instance().open(mDevice) != null;
if (mOpened) {
Log.i(getClass().getSimpleName(), "switchSerialPort: 成功打开串口");
} else {
Log.i(getClass().getSimpleName(), "switchSerialPort: 打开串口失败");
}
}
}
protected void sendData(String cmd) {
SerialPortManager.instance().sendCommand(cmd);
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(IMessage message) {
// 收到时间,刷新界面
refreshCurrentTemp(message.getMessage());
}
private void refreshCurrentTemp(String message) {
Log.i(getClass().getSimpleName(), "refreshCurrentTemp: "+message);
}
}
3.Device Bean 类
public class Device {
private String path;
private String baudrate;
public Device() {
}
public Device(String path, String baudrate) {
this.path = path;
this.baudrate = baudrate;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getBaudrate() {
return baudrate;
}
public void setBaudrate(String baudrate) {
this.baudrate = baudrate;
}
@Override
public String toString() {
return "Device{" + "path='" + path + ''' + ", baudrate='" + baudrate + ''' + '}';
}
}
4.基于单例的全局串口管理器
public class SerialPortManager {
private static final String TAG = "SerialPortManager";
private SerialReadThread mReadThread;
private OutputStream mOutputStream;
private HandlerThread mWriteThread;
private Scheduler mSendScheduler;
private static class InstanceHolder {
public static SerialPortManager sManager = new SerialPortManager();
}
public static SerialPortManager instance() {
return InstanceHolder.sManager;
}
private SerialPort mSerialPort;
private SerialPortManager() {
}
public SerialPort open(Device device) {
return open(device.getPath(), device.getBaudrate());
}
public SerialPort open(String devicePath, String baudrateString) {
if (mSerialPort != null) {
close();
}
try {
File device = new File(devicePath);
int baurate = Integer.parseInt(baudrateString);
mSerialPort = new SerialPort(device, baurate);
mReadThread = new SerialReadThread(mSerialPort.getInputStream());
mReadThread.start();
mOutputStream = mSerialPort.getOutputStream();
mWriteThread = new HandlerThread("write-thread");
mWriteThread.start();
mSendScheduler = AndroidSchedulers.from(mWriteThread.getLooper());
return mSerialPort;
} catch (Throwable tr) {
LogPlus.e(TAG, "打开串口失败", tr);
close();
return null;
}
}
public void close() {
if (mReadThread != null) {
mReadThread.close();
}
if (mOutputStream != null) {
try {
mOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (mWriteThread != null) {
mWriteThread.quit();
}
if (mSerialPort != null) {
mSerialPort.close();
mSerialPort = null;
}
}
private void sendData(byte[] datas) throws Exception {
mOutputStream.write(datas);
}
private Observable
5.读串口线程
public class SerialReadThread extends Thread {
private static final String TAG = "SerialReadThread";
private BufferedInputStream mInputStream;
public SerialReadThread(InputStream is) {
mInputStream = new BufferedInputStream(is);
}
@Override
public void run() {
byte[] received = new byte[1024];
int size;
LogPlus.e("开始读线程");
while (true) {
if (Thread.currentThread().isInterrupted()) {
break;
}
try {
int available = mInputStream.available();
if (available > 0) {
size = mInputStream.read(received);
if (size > 0) {
onDataReceive(received, size);
}
} else {
// 暂停一点时间,免得一直循环造成CPU占用率过高
SystemClock.sleep(1);
}
} catch (IOException e) {
LogPlus.e("读取数据失败", e);
}
//Thread.yield();
}
LogPlus.e("结束读进程");
}
private void onDataReceive(byte[] received, int size) {
// TODO: 2018/3/22 解决粘包、分包等
String hexStr = ByteUtil.bytes2HexStr(received, 0, size);
LogManager.instance().post(new RecvMessage(hexStr));
}
public void close() {
try {
mInputStream.close();
} catch (IOException e) {
LogPlus.e("异常", e);
} finally {
super.interrupt();
}
}
}
6.实现用于通信的消息类
6.1 日志消息数据接口
public interface IMessage {
String getMessage();
boolean isToSend();
}
6.2 log管理类
public class LogManager {
public final List messages;
private boolean mAutoEnd = true;
public LogManager() {
messages = new ArrayList<>();
}
private static class InstanceHolder {
public static LogManager sManager = new LogManager();
}
public static LogManager instance() {
return InstanceHolder.sManager;
}
public void add(IMessage message) {
messages.add(message);
}
public void post(IMessage message) {
EventBus.getDefault().post(message);
}
public void clear() {
messages.clear();
}
public boolean isAutoEnd() {
return mAutoEnd;
}
public void setAutoEnd(boolean autoEnd) {
mAutoEnd = autoEnd;
}
public void changAutoEnd() {
mAutoEnd = !mAutoEnd;
}
}
6.3 收到的日志
public class RecvMessage implements IMessage {
private String command;
private String message;
public static final SimpleDateFormat DEFAULT_FORMAT =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
public RecvMessage(String command) {
this.command = command;
this.message = currentTime() + " 收到命令:" + command;
}
@Override
public String getMessage() {
return message;
}
@Override
public boolean isToSend() {
return false;
}
public static String currentTime() {
Date date = new Date();
return DEFAULT_FORMAT.format(date);
}
}
6.4 发送的日志
public class SendMessage implements IMessage {
private String command;
private String message;
public SendMessage(String command) {
this.command = command;
this.message = currentTime() + " 发送命令:" + command;
}
@Override
public String getMessage() {
return message;
}
@Override
public boolean isToSend() {
return true;
}
}
7.Demo下载使用时集成基础接口调用即可,获取数据采取重写接口方法
| Demo | 适用场景 |
|---|---|
| Demo 1 点击下载已加速 | 基于JNI读写底层,无须升级Android x 以及API 29 |
| Demo 2 点击下载已加速 | 基于android 标准接口,支持较低版本的Gradle |



