本次的串口开发是基于Google的Serialport-api库实现的Android应用程序与硬件设备进行的串口通信(调用C层代码基于JNA)。
所以首先需要去Github上下载google-Serailport-api的源码,下载地址:Google-Serailport-api
下载下来以后,在自己的Android studio上创建一个Android工程,创建一个跟google源码相同包路径的一个包,如下图:
步骤如下:
1.从google-serialport-api项目下拷贝SerialPort和SerialPortFinder两个类到android_serialport_api包下放置。
而jniLibs文件夹下放置如下图的文件,文件也来源于google项目,另外jna的libjnidispatch.so文件可以去github上搜索源项目获取对应cup架构下的.so文件:
image.png
3.下图文件时JNA所需
image.png
必备的环境就是以上这些,下面我贴出我自己的调用示例代码:
封装了一个串口Api调用代理类
public class GoogleSerialPortUtils {
private InputStream inputStream;
private OutputStream outputStream;
private ReceiveThread mReceiveThread;
private boolean isStart = false;
private int baudRate = 115200;
private Activity activity;
private TextView textView;
public GoogleSerialPortUtils() {
}
private static GoogleSerialPortUtils googleSerialPortUtils = null;
public static GoogleSerialPortUtils instance() {
if (googleSerialPortUtils == null) {
synchronized (GoogleSerialPortUtils.class) {
if (googleSerialPortUtils == null) {
googleSerialPortUtils = new GoogleSerialPortUtils();
}
}
}
return googleSerialPortUtils;
}
//打开,连接串口
public void connectSerialPort(Activity activity, int baudRate, String serialPortPath,
TextView textView) {
this.activity = activity;
this.baudRate = baudRate;
this.textView = textView;
String[] allDevicesPath = new SerialPortFinder().getAllDevicesPath();
if (allDevicesPath != null && allDevicesPath.length > 0) {
for (int i = 0; i < allDevicesPath.length; i++) {
Log.i(TGFingerAPI.TAG, " 串口的名字:" + allDevicesPath[i]);
if (serialPortPath.equals(allDevicesPath[i])) {
Log.i(TGFingerAPI.TAG, " SerialPort长度 ===== :" + allDevicesPath.length
+ " 名称:" + allDevicesPath[i]);
try {
SerialPort serialPort = new SerialPort(new File(allDevicesPath[i]), baudRate, 0);
//调用serialPort对象,获取读和写的数据流
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
if (inputStream != null && outputStream != null) {
Log.i(TGFingerAPI.TAG, " SerialPort 连接成功 ===== pathName:" + allDevicesPath[i]);
isStart = true;
}
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
}
/**
* 关闭串口
* 关闭串口中的输入输出流
*/
public void closeSerialPort() {
Log.i(TGFingerAPI.TAG, "关闭串口");
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
isStart = false;
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMsgSerailPort(String sendMsgs) {
if (!TextUtils.isEmpty(sendMsgs)) {
byte[] sendData = MyFunc.HexToByteArr("123456789"/*sendMsgs*/);
try {
outputStream.write(sendData);
outputStream.flush();
Log.i(TGFingerAPI.TAG, " 发送数据");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void getSerialPort() {
if (mReceiveThread == null) {
mReceiveThread = new ReceiveThread();
}
if (!mReceiveThread.isAlive()) {
mReceiveThread.start();
}
}
public void destroyTh() {
if (mReceiveThread != null && mReceiveThread.isAlive()) {
mReceiveThread.interrupt();
}
}
/**
* 接收串口数据的线程
*/
private class ReceiveThread extends Thread {
@Override
public void run() {
super.run();
while (isStart) {
if (inputStream == null) {
return;
}
byte[] readData = new byte[1024];
try {
int size = inputStream.read(readData);
if (size > 0) {
final String readString = DataUtils.bytesToHex(readData/*, 0, size*/);
// Log.i(TGFingerAPI.TAG, " 接收到的数据:" + readString
// + " 线程的名称:" + Thread.currentThread().getName());
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(readString);
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
调用的位置
private static final String SERIAL_PORT_PATH = "/dev/ttyS0"/*"/dev/ttysWK2"*/;//
private static final int RATE = 115200;
private void innitPermission() {
//申请权限
int i = ContextCompat.checkSelfPermission(this, p[0]);
if (i != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, p, 0x12);
} else {
//连接串口
GoogleSerialPortUtils.instance().connectSerialPort(this, RATE,
SERIAL_PORT_PATH, receiveMsg);
}
}
连接串口的时候,要找对你主机和硬件设备的波特率以及平板主机的TTL串口地址,如果不是TTL串口地址,会导致串口通信失败
通过串口发送消息
case R.id.sendMsg:
String sendMsgs = sendContent.getText().toString().trim();
GoogleSerialPortUtils.instance().sendMsgSerailPort(sendMsgs);
break;
获取串口的消息
//接收数据
GoogleSerialPortUtils.instance().getSerialPort();
关闭串口
@Override
protected void onDestroy() {
super.onDestroy();
GoogleSerialPortUtils.instance().closeSerialPort();
GoogleSerialPortUtils.instance().destroyTh();
// FireFlySerialPortUtils.instance().closeSerailPort();
}
注意:如果你在连接硬件时候,你硬件的通信库也是需要是用串口往上层发送消息,这个时候你就不能在上层代码中开启google的轮询获取串口消息的接口,否则会占用通信库层的串口通信。上图的糊掉的就是我自己的通信库,当然并不是每个项目都会用自己的通信库。具体项目具体调试
另外贴上串口通信Android端的调试工具,PC端的串口调试工具可使用友善串口调试工具
只要平板端与PC端的串口调试工具间能够相互收发消息,即串口已经接通。串口地址一定要找对,否则够你头大的!!祝好运!!!~
网友评论