此次串口开发参考了开源项目android-serialport-api开发,但是一直遇到读取数据问题
开发步骤:
1.修改SerialPort.c文件方法名,使之与包名类名一致,具体请学习jni开发
2.修改SerialPort.java,使用java发送cmd命令关闭selinux防火墙并添加权限操作文件
3.修改Application.java,设置与自己设备对应的端口和波特率并返回串口,获取输入输出流以便操作文件
问题描述:
ReadThread一直阻塞在mInputStream.read(buffer),所以一直读不出数据。
现象:
每次开机重启可以读取到数据,之后就很难读取到,只有偶尔才能读取到一次。(注:因为我的设备问题,不能主动退出app,所以只能重启退出,大家可以根据自身情况尝试重启手机或app观察现象)
原因:线程问题。
因为每次跳转activity都会重新创建并启动一个ReadThread,而就算创建线程的activity销毁了,线程也还一直存在,并阻塞在读取输入流的方法上,所以就造成了线程一直在增加的情况。而第二次跳转activity时,因为第一次跳转开启的线程还在运行,并且阻塞在读取数据的方法上,因此基本上每次都会是之前的那个线程把数据读取了,所以跳转时新创建的线程未能读取到此次发送指令返回的数据,就又会等待并读取到下一次的数据,所以就造成了除了重启后,每次读取数据线程都会无法读取数据并阻塞在read方法上的假象。
解决方法:
去除掉ReadThread的循环,每次发送AT指令之前先开启线程,这样线程就会等待读取数据,当发送了AT指令之后返回一个输入流,这时线程就会读取数据并将自身销毁。这样每次跳转时开启的新线程就可以读取到数据了。有兴趣的可以参考参考我的源代码。
CSDN下载地址:项目地址
GitHub地址:项目代码
下面贴上部分代码示例:
package android_serialport_api.sample;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;
import android.R.string;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Message;
import android.util.Log;
import android.widget.EditText;
import android_serialport_api.SerialPort;
import android_serialport_api.sample.SerialPortActivity.ReadThread;
import android_serialport_api.util.HexUtils;
/**
* @author dengjifu
*/
public class TestActivity extends Activity implements Callback {
private static final String TAG = "TestActivity";
private static int SamCard1 = 12;
private static int SamCard2 = 14;
private static String path1 = "/dev/ttyMT0";
private static String path2 = "/dev/ttyMT1";
private static int baudrate = 38400;
private EditText rspEditText;
protected Application mApplication;
protected SerialPort mSerialPort;
protected OutputStream mOutputStream;
protected InputStream mInputStream;
private ReadThread mReadThread;
private String respTextString;
public class ReadThread extends Thread {
@Override
public void run() {
super.run();
Log.i("dengjifu", Thread.currentThread().getName()
+ "--ReadThread/isInterrupted():" + isInterrupted());
try {
byte[] buffer = new byte[1024];
if (mInputStream == null) {
Log.i("dengjifu", "mInputStream == null");
return;
}
Log.i("dengjifu", "ReadThread-->read");
int size = mInputStream.read(buffer);
Log.i("dengjifu", "size:" + size);
if (size > 0) {
onDataReceived(buffer, size);
}
Log.i("dengjifu", Thread.currentThread().getName()
+ "--ReadThread/isInterrupted():" + isInterrupted());
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
rspEditText = (EditText) findViewById(R.id.rspEditText);
rspEditText.setSaveEnabled(false);
mApplication = (Application) getApplication();
try {
// 串口操作初始化
mSerialPort = mApplication.getSerialPort();
mOutputStream = mSerialPort.getOutputStream();
mInputStream = mSerialPort.getInputStream();
mReadThread = new ReadThread();
mReadThread.start();
} catch (InvalidParameterException e1) {
e1.printStackTrace();
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
// 上电GPIO
pownOn(SamCard1);
pownOn(SamCard2);
// 发送AT指令
try {
sendATCmds();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendATCmds() throws SecurityException, IOException {
Runnable sendCmdRunnable = new Runnable() {
@Override
public void run() {
try {
// 66 00 00 00 00 00 00 02 00 00 60
String cmd = new String("6200000000000200000060");
byte[] buffer = HexUtils.HexToByteArr(cmd);
Log.i("dengjifu", mOutputStream + ":" + buffer);
mOutputStream.write(buffer);
mOutputStream.write('\r');
mOutputStream.write('\n');
Log.i("dengjifu",
"Send AT command: " + HexUtils.byte2HexStr(buffer));
} catch (Exception e) {
e.printStackTrace();
}
}
};
new Thread(sendCmdRunnable).start();
}
private void pownOn(int portid) {
Intent i = new Intent("testsam.SAMCARD_POWER_UP");
i.putExtra("gpio_port_id", portid);
sendBroadcast(i);
Log.i("dengjifu", "GPIO pownOn!");
}
private void pownOff(int portid) {
Intent i = new Intent("testsam.SAMCARD_POWER_DOWN");
i.putExtra("gpio_port_id", portid);
sendBroadcast(i);
Log.i("dengjifu", "GPIO pownOff!");
}
@Override
protected void onDestroy() {
super.onDestroy();
}
protected void onDataReceived(byte[] buffer, int size) {
respTextString = HexUtils.byte2HexStr(buffer);
Log.i("dengjifu", "buffer:" + respTextString + ",size" + size);
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
Handler handler = new Handler(this);
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 1:
rspEditText.setText(respTextString);
break;
default:
break;
}
return false;
}
}