因爲要寫串口功能檢測串口是否正常,也是參考了網上很多博客和例程,從中取出自己需要的,捨棄不需要的,再加以優化,就是這麼個過程了.
這是我的串口功能的目錄結構:
實際上把jni和libs文件夾建好,導入網上下載的相關文件,然後把SerialPort.java和SerialPortFinder.java放入android_serialport_api包下(要注意這兩個類必須放入這個包下,聽說和libs中的動態鏈接庫有關係,反正你就放到這個包裏面就行了,不用多想).
先創建一個SerialPortActivity,源碼如下:
public abstract class SerialPortActivity extends Activity {
protected SerialPort mSerialPort;
protected OutputStream mOutputStream;
private InputStream mInputStream;
private ReadThread mReadThread;
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
while (!isInterrupted()) {
int size;
try {
byte[] buffer = new byte[64];
if (mInputStream == null) {
return;
}
size = mInputStream.read(buffer);
if (size > 0) {
onDataReceived(buffer, size);
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
private void DisplayError(int resourceId) {
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle("Error");
b.setMessage(resourceId);
b.setPositiveButton("OK", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//SerialPortActivity.this.finish();
}
});
b.show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public boolean OpenSerialPort(String path, int baudrate) {
try {
mSerialPort = getSerialPort(path, baudrate);
mOutputStream = mSerialPort.getOutputStream();
mInputStream = mSerialPort.getInputStream();
/* Create a receiving thread 創建一個接受數據的線程 */
mReadThread = new ReadThread();
mReadThread.start();
} catch (SecurityException e) {
DisplayError(R.string.error_security);
return false;
} catch (IOException e) {
DisplayError(R.string.error_unknown);
return false;
} catch (InvalidParameterException e) {
DisplayError(R.string.error_configuration);
return false;
}
return true;
}
public SerialPort getSerialPort(String path, int baudrate) throws SecurityException, IOException, InvalidParameterException {
if (mSerialPort == null) {
/* Check parameters */
if ((path.length() == 0) || (baudrate == -1)) {
throw new InvalidParameterException();
}
/* Open the serial port */
// mSerialPort = new SerialPort(new File("/dev/ttySAC1"), 9600, 0);
mSerialPort = new SerialPort(new File(path), baudrate, 0);
}
return mSerialPort;
}
protected abstract void onDataReceived(final byte[] buffer, final int size);
@Override
protected void onDestroy() {
if (mReadThread != null)
mReadThread.interrupt();
if (mSerialPort != null) {
mSerialPort.close();
mSerialPort = null;
}
super.onDestroy();
}
}
在這個Activity裏面打開串口,創建ReadThread讀取數據,還有提示串口的各種錯誤信息.
再創建一個活動ConsoleActivity繼承自SerialPortActivity,源碼如下:
public class ConsoleActivity extends SerialPortActivity {
private TextView serialNumTxt,baudrateTxt;
private EditText mReception;
private EditText Emission;
private TextView stateTxt;
static String serialDevPath = "/dev/ttyS0";//待測試串口路徑
String str;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.console);
//初始化控件
initView();
boolean flag = ConsoleActivity.super.OpenSerialPort(serialDevPath, 9600);
//發送數據
if (!flag) {
stateTxt.setText(R.string.falseState);
stateTxt.setTextColor(Color.RED);
return;
}
stateTxt.setText(R.string.trueState);
stateTxt.setTextColor(Color.GREEN);
CharSequence t = Emission.getText();
char[] text = new char[t.length()];
for (int i = 0; i < t.length(); i++) {
text[i] = t.charAt(i);
}
try {
mOutputStream.write(new String(text).getBytes());
//mOutputStream.write(' ');
} catch (IOException e) {
e.printStackTrace();
}
}
private void initView() {
// TODO Auto-generated method stub
mReception = (EditText) findViewById(R.id.EditTextReception);
mReception.setEnabled(false);
mReception.setFocusable(false);
mReception.setTextColor(Color.WHITE);
Emission = (EditText) findViewById(R.id.EditTextEmission);
Emission.setEnabled(false);
Emission.setFocusable(false);
Emission.setText("Hello,World!");
stateTxt=(TextView)findViewById(R.id.stateTxt);
serialNumTxt = (TextView)findViewById(R.id.serialportNum);
serialNumTxt.setText(this.getResources().getString(R.string.serialName)+serialDevPath);
baudrateTxt = (TextView)findViewById(R.id.baundrate);
baudrateTxt.setText(this.getResources().getString(R.string.baundrate)+"9600");
}
@Override
protected void onDataReceived(final byte[] buffer, final int size) {
runOnUiThread(new Runnable() {
public void run() {
// if (mReception != null) {
mReception.append(new String(buffer, 0, size));
//mReception.append(" ");
// }
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// 創建退出對話框
AlertDialog.Builder isExit = new Builder(this);
// 設置對話框標題
isExit.setTitle("BRIGHTNESS Test");
// 設置對話框消息
isExit.setMessage("測試通過");
// 添加選擇按鈕並註冊監聽
isExit.setPositiveButton("同意", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
str = "yes";
Uri data = Uri.parse(str);
Intent result = new Intent(null, data);
setResult(RESULT_OK, result);
finish();
}
});
isExit.setNegativeButton("否定", new android.content.DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
str = "no";
Uri data = Uri.parse(str);
Intent result = new Intent(null, data);
setResult(RESULT_OK, result);
finish();
}
});
// 對話框顯示
isExit.create().show();
}
return false;
}
}
這裏我是固定設置的串口號,你可以通過SerialPortFinder類的getAllDevices方法找到所有的串口號,然後加到一個Spinner中,再設置OnItemSelectedLisener就可以實現選擇串口號的功能.
佈局文件源碼如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal" >
<TextView
android:id="@+id/serialportNum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="100dp"
android:gravity="center_horizontal"
android:text="@string/serialName"
android:textSize="@dimen/serialSize" />
<TextView
android:id="@+id/baundrate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/serialportNum"
android:layout_marginTop="10dp"
android:layout_alignLeft="@id/serialportNum"
android:text="@string/baundrate"
android:textSize="@dimen/serialSize" />
<TextView
android:id="@+id/sendArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/baundrate"
android:layout_marginTop="10dp"
android:layout_alignLeft="@id/serialportNum"
android:text="@string/send"
android:textSize="@dimen/serialSize" />
<EditText
android:id="@+id/EditTextEmission"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/sendArea"
android:layout_alignBottom="@id/sendArea"
android:layout_weight="1" />
<TextView
android:id="@+id/recArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/sendArea"
android:layout_marginTop="10dp"
android:layout_alignLeft="@id/sendArea"
android:text="@string/rec"
android:textSize="@dimen/serialSize" />
<EditText
android:id="@+id/EditTextReception"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/recArea"
android:layout_alignBottom="@id/recArea"
android:layout_weight="1" />
<TextView android:id="@+id/serialState"
android:layout_below="@id/recArea"
android:layout_alignLeft="@id/serialportNum"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/serialState"
android:textSize="@dimen/serialSize"
android:textAlignment="viewStart" />
<TextView android:id="@+id/stateTxt"
android:layout_toRightOf="@id/serialState"
android:layout_alignBottom="@id/serialState"
android:layout_alignLeft="@id/EditTextReception"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textSize="@dimen/serialSize" />
</RelativeLayout>
最後實現的界面如下:
網上例程很多,我之前是已經把網上的一個例程給調通了,但是想把這個串口功能作爲一個子活動加入我的項目中,卻是各種崩潰,原因也找不到,現在能OK也是經歷一番摸索,不容易.網上的例程有的是通過Application來把找到的串口號列表加入全局變量,有的是sharedpreferrce保存設置過的參數,這些我都沒要,做到了簡化的極限了.
在網上看到說在6.0以上版本運行會報錯,但是我沒有發現這情況,只是使用外部庫總是會彈窗提示text location,這個問題還不知道怎麼解決.
想把這個功能加入某個項目中作爲子活動的話只要在主活動中通過Intent跳到ConsoleActivity中就可以了,很方便.
調試用的設備不知道什麼原因沒有LOG打印,只能在代碼中通過註釋某一部分來確定問題所在.
2018年3月28日 16:38:29
現在此功能已經完全OK了,解決彈窗請看解決串口彈窗
2018年4月24日 20:23:17
相比大的項目,各種獨立的小Demo才應該是我們要保留的對象,我對此感受頗深.
又有Android串口相關的項目,我從大項目中將串口測試模塊單獨拿出來,卻莫名其妙崩潰,一整天弄的我心態都要炸了,終於在此時此刻,運行OK,沒有崩潰的情況了,在此把Demo分享出來,免得下次又有意外.