Android 串口通信笔记2 调试工具分析 工具类实现分析、项目实现
1.调试工具ComAssistant 分析
![](https://upload-images.jianshu.io/upload_images/2728246-1c7c61afa645f0a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
ComAssistant
Android 端调试工具ComAssistant 如图,处于何人之手已不可考,找到的源码是用eclipse 写的。源码见文末分享。
此串口调试工具,可以同时对四个串口读写是四个独立的线程,选定串口路径 ,Linux把每个硬件也看作是一个文件,所以都是“dev/ttyS1”这种的。
注意:官方提供的 demo 没有N-8-1( N 不奇偶校验位 8 8个数据位 1 1个停止位)的设定。
第一次根据设备终端说明或者自己尝试连接电脑打开调试助手 查看到底哪个口对应哪个路径。
2.源码分析:
Eclipse版本的从哪个资源网站下载的忘记了,不过解压看是2012年8月的,所以这里边的api 适配到10(API等级10:Android 2.3.3-2.3.7 Gingerbread 姜饼),Eclipse项目结构:
![](https://upload-images.jianshu.io/upload_images/2728246-d2b12301f0e11454.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/640)
Eclipse项目结构
从结构中可以看出来 是把Android官方提供的android_serial_api 从项目包中独立出来,此源码唯一不好的是 GBK 编码的 导入Android Studio中时 乱码 要从新折腾。
SerialPortFinder与SerialPort分析:
![](https://upload-images.jianshu.io/upload_images/2728246-3c4ea8ad8367cbba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
SerialPortFinder
SerialPortFinder就是遍历获取设备上所有devices以及对应的path;
public class SerialPort {
private static final String TAG = "SerialPort";
/*
* Do not remove or rename the field mFd: it is used by native method close();
*/
private FileDescriptor mFd;
private FileInputStream mFileInputStream;
private FileOutputStream mFileOutputStream;
public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
/* Check access permission */
if (!device.canRead() || !device.canWrite()) {
try {
/* Missing read/write permission, trying to chmod the file */
Process su;
su = Runtime.getRuntime().exec("/system/bin/su");
String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ "exit\n";
su.getOutputStream().write(cmd.getBytes());
if ((su.waitFor() != 0) || !device.canRead()
|| !device.canWrite()) {
throw new SecurityException();
}
} catch (Exception e) {
e.printStackTrace();
throw new SecurityException();
}
}
mFd = open(device.getAbsolutePath(), baudrate, flags);
if (mFd == null) {
Log.e(TAG, "native open returns null");
throw new IOException();
}
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
}
// Getters and setters
public InputStream getInputStream() {
return mFileInputStream;
}
public OutputStream getOutputStream() {
return mFileOutputStream;
}
// JNI
private native static FileDescriptor open(String path, int baudrate, int flags);
public native void close();
static {
System.loadLibrary("serial_port");
}
}
创建了打开串口和关闭串口的本地方法,在jni中实现,给Java层调用。
主要是分析 SerialHelp和 Activity的实现逻辑,SerialHelper代码:
public abstract class SerialHelper{
private SerialPort mSerialPort;
private OutputStream mOutputStream;
private InputStream mInputStream;
private ReadThread mReadThread;
private SendThread mSendThread;
private String sPort="/dev/s3c2410_serial0";
private int iBaudRate=9600;
private boolean _isOpen=false;
private byte[] _bLoopData=new byte[]{0x30};
private int iDelay=500;
//----------------------------------------------------
public SerialHelper(String sPort,int iBaudRate){
this.sPort = sPort;
this.iBaudRate=iBaudRate;
}
public SerialHelper(){
this("/dev/s3c2410_serial0",9600);
}
public SerialHelper(String sPort){
this(sPort,9600);
}
public SerialHelper(String sPort,String sBaudRate){
this(sPort,Integer.parseInt(sBaudRate));
}
//----------------------------------------------------
public void open() throws SecurityException, IOException,InvalidParameterException{
File device = new File(sPort);
//检查访问权限,如果没有读写权限,进行文件操作,修改文件访问权限
if (!device.canRead() || !device.canWrite()) {
try {
//通过挂在到linux的方式,修改文件的操作权限
Process su = Runtime.getRuntime().exec("/system/bin/su");
//一般的都是/system/bin/su路径,有的也是/system/xbin/su
String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n";
su.getOutputStream().write(cmd.getBytes());
if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
throw new SecurityException();
}
} catch (Exception e) {
e.printStackTrace();
throw new SecurityException();
}
}
mSerialPort = new SerialPort(new File(sPort), iBaudRate, 0);
mOutputStream = mSerialPort.getOutputStream();
mInputStream = mSerialPort.getInputStream();
mReadThread = new ReadThread();
mReadThread.start();
mSendThread = new SendThread();
mSendThread.setSuspendFlag();
mSendThread.start();
_isOpen=true;
}
//----------------------------------------------------
public void close(){
if (mReadThread != null)
mReadThread.interrupt();
if (mSerialPort != null) {
mSerialPort.close();
mSerialPort = null;
}
_isOpen=false;
}
//----------------------------------------------------
public void send(byte[] bOutArray){
try
{
mOutputStream.write(bOutArray);
} catch (IOException e)
{
e.printStackTrace();
}
}
//----------------------------------------------------
public void sendHex(String sHex){
byte[] bOutArray = MyFunc.HexToByteArr(sHex);
send(bOutArray);
}
//----------------------------------------------------
public void sendTxt(String sTxt){
byte[] bOutArray =sTxt.getBytes();
send(bOutArray);
}
//----------------------------------------------------
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
while(!isInterrupted()) {
try
{
if (mInputStream == null) return;
byte[] buffer=new byte[512];
int size = mInputStream.read(buffer);
if (size > 0){
ComBean ComRecData = new ComBean(sPort,buffer,size);
onDataReceived(ComRecData);
}
try
{
Thread.sleep(50);//延时50ms
} catch (InterruptedException e)
{
e.printStackTrace();
}
} catch (Throwable e)
{
e.printStackTrace();
return;
}
}
}
}
//----------------------------------------------------
private class SendThread extends Thread{
public boolean suspendFlag = true;// 控制线程的执行
@Override
public void run() {
super.run();
while(!isInterrupted()) {
synchronized (this)
{
while (suspendFlag)
{
try
{
wait();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
send(getbLoopData());
try
{
Thread.sleep(iDelay);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
//线程暂停
public void setSuspendFlag() {
this.suspendFlag = true;
}
//唤醒线程
public synchronized void setResume() {
this.suspendFlag = false;
notify();
}
}
//----------------------------------------------------
public int getBaudRate()
{
return iBaudRate;
}
public boolean setBaudRate(int iBaud)
{
if (_isOpen)
{
return false;
} else
{
iBaudRate = iBaud;
return true;
}
}
public boolean setBaudRate(String sBaud)
{
int iBaud = Integer.parseInt(sBaud);
return setBaudRate(iBaud);
}
//----------------------------------------------------
public String getPort()
{
return sPort;
}
public boolean setPort(String sPort)
{
if (_isOpen)
{
return false;
} else
{
this.sPort = sPort;
return true;
}
}
//----------------------------------------------------
public