Android--關於串列埠通訊
阿新 • • 發佈:2022-03-25
利用串列埠,可以讓Android主機板與各種感測器和智慧裝置之間通訊。Google自己有一個關於Android串列埠通訊。
整合環境
一般串列埠通訊開發,需要用到JNI和NDK方面的知識。首先需要搭建環境,匯入相應的.so檔案(.so檔案是Unix的動態連線庫,本身是二進位制檔案,是由C/C++編譯而來的),沒有就自己新建libs,將.so檔案複製進去。
之後需要再Gradle檔案,將libs中的東西引入編譯,不然訪問不到。如下圖
android { compileSdkVersion 30 buildToolsVersion "30.0.3" defaultConfig { ...... /*選擇處理器相應的架構*/ ndk { abiFilters "armeabi" } testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } ..... /*載入 so庫*/ sourceSets { main { jniLibs.srcDirs = ['libs'] } } }
Google的demo中的 SerialPort.java (串列埠程式碼)
/* * Copyright 2009 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android_serialport_api; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.util.Log; 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;//輸出流 // 裝置號(串列埠地址),波特率,flags 預設為0 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"); } } // 如何使用 SerialPort serial = new SerialPort(new File("/dev/goc_serial"),115200,0); **[SerialPortUtil](https://juejin.cn/post/6844903606982967303)** public class SerialPortUtil { private SerialPort serialPort = null; private InputStream inputStream = null; private OutputStream outputStream = null; private ReceiveThread mReceiveThread = null; private boolean isStart = false; /** * 開啟串列埠,接收資料 * 通過串列埠,接收單片機發送來的資料 */ public void openSerialPort() { try { serialPort = new SerialPort(new File("/dev/ttyS0"), 9600, 0); //呼叫物件SerialPort方法,獲取串列埠中"讀和寫"的資料流 inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); isStart = true; } catch (IOException e) { e.printStackTrace(); } getSerialPort(); } /** * 關閉串列埠 * 關閉串列埠中的輸入輸出流 */ public void closeSerialPort() { Log.i("test", "關閉串列埠"); try { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } isStart = false; } catch (IOException e) { e.printStackTrace(); } } /** * 傳送資料 * 通過串列埠,傳送資料到微控制器 * * @param data 要傳送的資料 */ public void sendSerialPort(String data) { try { byte[] sendData = DataUtils.HexToByteArr(data);//字串轉為位元組陣列 outputStream.write(sendData); outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } } private void getSerialPort() { if (mReceiveThread == null) { mReceiveThread = new ReceiveThread(); } mReceiveThread.start(); } /** * 接收串列埠資料的執行緒 */ private class ReceiveThread extends Thread { @Override public void run() { super.run(); while (isStart) { if (inputStream == null) { return; } byte[] readData = new byte[1024]; try { int size = inputStream.read(readData); if (size > 0) { String readString = DataUtils.ByteArrToHex(readData, 0, size);//位元組陣列轉為字串 //EventBus.getDefault().post(readString);事件通知,拿到資料 } } catch (IOException e) { e.printStackTrace(); } } } } }