用到谷歌开源serialPort api
下载链接:serialPort-api
以下项目用的so库是谷歌原库,没有做修改
新建项目:
1、先把下载的api中这些文件拷进项目的相应位置
SerialPort类是咱们Android可以调用的类,
jni目录下放着c源码和h头文件,
jniLibs下面放的就是so库。
注意:因为用的谷歌原生so库,所以SerialPort类的包名一定要是android_serialport_api,如果想修改这个包名,就需要重新生成对应的so库
这是SerialPort类,里面的open和close方法在报错,这个不用管。
2、在build.gradle中添加如下代码:
sourceSets {
main { jni.srcDirs = [] }
}
3、这样就可以串口通信了
这是串口操作类:
package utils;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android_serialport_api.SerialPort;
/**
* Created by WangChaowei on 2017/12/7.
*/
public class SerialPortUtils {
private final String TAG = "SerialPortUtils";
private String path = "/dev/ttyS1";
private int baudrate = 9600;
public boolean serialPortStatus = false; //是否打开串口标志
public String data_;
public boolean threadStatus; //线程状态,为了安全终止线程
public SerialPort serialPort = null;
public InputStream inputStream = null;
public OutputStream outputStream = null;
public ChangeTool changeTool = new ChangeTool();
/**
* 打开串口
* @return serialPort串口对象
*/
public SerialPort openSerialPort(){
try {
serialPort = new SerialPort(new File(path),baudrate,0);
this.serialPortStatus = true;
threadStatus = false; //线程状态
//获取打开的串口中的输入输出流,以便于串口数据的收发
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
new ReadThread().start(); //开始线程监控是否有数据要接收
} catch (IOException e) {
Log.e(TAG, "openSerialPort: 打开串口异常:" + e.toString());
return serialPort;
}
Log.d(TAG, "openSerialPort: 打开串口");
return serialPort;
}
/**
* 关闭串口
*/
public void closeSerialPort(){
try {
inputStream.close();
outputStream.close();
this.serialPortStatus = false;
this.threadStatus = true; //线程状态
serialPort.close();
} catch (IOException e) {
Log.e(TAG, "closeSerialPort: 关闭串口异常:"+e.toString());
return;
}
Log.d(TAG, "closeSerialPort: 关闭串口成功");
}
/**
* 发送串口指令(字符串)
* @param data String数据指令
*/
public void sendSerialPort(String data){
Log.d(TAG, "sendSerialPort: 发送数据");
try {
byte[] sendData = data.getBytes(); //string转byte[]
this.data_ = new String(sendData); //byte[]转string
if (sendData.length > 0) {
outputStream.write(sendData);
outputStream.write('\n');
//outputStream.write('\r'+'\n');
outputStream.flush();
Log.d(TAG, "sendSerialPort: 串口数据发送成功");
}
} catch (IOException e) {
Log.e(TAG, "sendSerialPort: 串口数据发送失败:"+e.toString());
}
}
/**
* 单开一线程,来读数据
*/
private class ReadThread extends Thread{
@Override
public void run() {
super.run();
//判断进程是否在运行,更安全的结束进程
while (!threadStatus){
Log.d(TAG, "进入线程run");
//64 1024
byte[] buffer = new byte[64];
int size; //读取数据的大小
try {
size = inputStream.read(buffer);
if (size > 0){
Log.d(TAG, "run: 接收到了数据:" + changeTool.ByteArrToHex(buffer));
Log.d(TAG, "run: 接收到了数据大小:" + String.valueOf(size));
onDataReceiveListener.onDataReceive(buffer,size);
}
} catch (IOException e) {
Log.e(TAG, "run: 数据读取异常:" +e.toString());
}
}
}
}
//这是写了一监听器来监听接收数据
public OnDataReceiveListener onDataReceiveListener = null;
public static interface OnDataReceiveListener {
public void onDataReceive(byte[] buffer, int size);
}
public void setOnDataReceiveListener(OnDataReceiveListener dataReceiveListener) {
onDataReceiveListener = dataReceiveListener;
}
}
4、activity中只贴串口数据监听事件
//串口数据监听事件
serialPortUtils.setOnDataReceiveListener(new SerialPortUtils.OnDataReceiveListener() {
@Override
public void onDataReceive(byte[] buffer, int size) {
Log.d(TAG, "进入数据监听事件中。。。" + new String(buffer));
//
//在线程中直接操作UI会报异常:ViewRootImpl$CalledFromWrongThreadException
//解决方法:handler
//
mBuffer = buffer;
handler.post(runnable);
}
//开线程更新UI
Runnable runnable = new Runnable() {
@Override
public void run() {
textView_status.setText("size:"+ String.valueOf(mBuffer.length)+"数据监听:"+ new String(mBuffer));
}
};
});