Android 之 串列埠通訊
阿新 • • 發佈:2019-02-16
閱讀前提:串列埠通訊是微控制器採用RS232與Android板進行通訊,首先要了解RS232傳送資料的工作原理:RS232傳送資料的時候是通過一個位元組接著一個位元組,將資料傳送出去,所以當接收資料時候也應當一個位元組一個位元組接受
在AndroidManifest.xml中加入許可權
/*允許程式對SD卡進行寫入*/
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
/*允許程式對SD卡進行讀取*/
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
1.登陸GitHub下載android-serialport-api
①首先,在main的資料夾中新建一個叫android_serialport_api的資料夾,並且把android_serialport_api中的中的SerialPort中的檔案複製到資料夾
②新建一個jni和jniLibs的資料夾,把android_serialport_api對應的檔案複製過來
2.建立SerialPortUtil單例模式
這裡簡單介紹:
單例模式:單例模式就是保證你全域性有且只有這個類的一個例項,這個例項可以在全域性使用,並且這個例項會為全域性提供訪問的節點
全域性的概念:全域性在這裡可以理解為整一個Application,這個類在整個Application中永遠只會被例項化一次(即new),當JVM檢測到這個例項不再使用就會被垃圾回收機制回收了,那麼當代碼執行到需要這個例項的時候,發現這個例項不存在就會把這個類再例項化一次,這樣就保證了記憶體中只有一個類的例項而不是多個例項
為什麼類只例項化一個:這裡涉及到一個記憶體的使用的問題,如果一個類被例項化了多次,在記憶體中就會佔有多個同一個類的多個例項,這樣就浪費記憶體,減慢程式碼執行效率。只使用一個例項可以節省記憶體,提高程式碼的執行效率。
在我這裡使用的是一個叫懶漢模式的單例模式
public class SerialPortUtil {
//這個就是需要被例項化的類
private static SerialPortUtil INSTANCE = null;
//這裡必須需要一個私有的構造器
private SerialPortUtil(){
}
//這裡為全域性提供訪問的節點
public static SerialPortUtil getInstance(){
//涉及延時載入,當需要這個類的時候才會被例項化
if (INSTANCE == null){
INSTANCE = new SerialPortUtil();
}
return INSTANCE;
}
}
當對串列埠進行資料的通訊時候,進行四個步驟:①開啟串列埠、②傳送資料、③接受資料、④關閉串列埠
//開啟串列埠
private void openSerialPort(){
try {
/*設定開啟的串列埠*/
final String portPath = "/dev/ttyS0";
/*設定波特率*/
final int baudRate = 115200;
serialPort = new SerialPort(new File(portPath),baudRate,0);
outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();
/*開啟執行緒讀取資料*/
new ReadThread().start();
}catch (IOException e){
e.printStackTrace();
}
}
//關閉串列埠
private void closeSerialPort(){
try{
inputStream.close();
outputStream.close();
serialPort.close();
}catch (IOException e){
e.printStackTrace();
}
}
//傳送資料
private void sendDataToSerialPort(byte[] data){
try{
int dataLength = data.length;
Log.d("DATASIZE",String.valueOf(dataLength));
if(dataLength > 0){
outputStream.write(data);
outputStream.write('\n');
outputStream.flush();
}
}catch (IOException e){
e.printStackTrace();
}
}
//接收資料的執行緒
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
while(!isInterrupted()) {
int size;
try {
byte[] buffer = new byte[64];
if (inputStream == null) return;
size = inputStream.read(buffer);
if (size > 0) {
SCMDataReceiveListener.dataRecevie(buffer, size);//監聽資料的傳輸
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
接收資料通過介面進行接收資料
//設定監聽介面
public void setSCMDataReceiveListener(SCMDataReceiveListener SCMDataReceiveListener) {
this.SCMDataReceiveListener = SCMDataReceiveListener;
}
3.SerialPortUtil原始碼
public class SerialPortUtil {
private static SerialPortUtil INSTANCE = null;
private SerialPort serialPort;
private OutputStream outputStream;
private InputStream inputStream;
private SCMDataReceiveListener SCMDataReceiveListener;
private SerialPortUtil(){
}
public static SerialPortUtil getInstance(){
if (INSTANCE == null){
INSTANCE = new SerialPortUtil();
}
return INSTANCE;
}
public void setSCMDataReceiveListener(SCMDataReceiveListener SCMDataReceiveListener) {
this.SCMDataReceiveListener = SCMDataReceiveListener;
}
private void openSerialPort(){
try {
final String portPath = "/dev/ttyS0";
final int baudRate = 115200;
serialPort = new SerialPort(new File(portPath),baudRate,0);
outputStream = serialPort.getOutputStream();
inputStream = serialPort.getInputStream();
new ReadThread().start();
}catch (IOException e){
e.printStackTrace();
}
}
public void closeSerialPort(){
try{
inputStream.close();
outputStream.close();
serialPort.close();
}catch (IOException e){
e.printStackTrace();
}
}
private void sendDataToSerialPort(byte[] data){
try{
int dataLength = data.length;
Log.d("DATASIZE",String.valueOf(dataLength));
if(dataLength > 0){
outputStream.write(data);
outputStream.write('\n');
outputStream.flush();
}
}catch (IOException e){
e.printStackTrace();
}
}
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
while(!isInterrupted()) {
int size;
try {
byte[] buffer = new byte[1];
if (inputStream == null) return;
size = inputStream.read(buffer);
if (size > 0) {
/*監聽資料接收*/
SCMDataReceiveListener.dataRecevie(buffer, size);
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
}
}
4.設定串列埠監聽回撥介面
public interface SCMDataReceiveListener {
void dataRecevie(byte[] data,int size);
}