1. 程式人生 > >Android串列埠通訊-AndroidStudio

Android串列埠通訊-AndroidStudio

用到谷歌開源serialPort api 
下載連結:serialPort-api

以下專案用的so庫是谷歌原庫,沒有做修改

 

新建專案:

1、先把下載的api中這些檔案拷進專案的相應位置 


SerialPort類是咱們Android可以呼叫的類,

jni目錄下放著c原始碼和h標頭檔案,

jniLibs下面放的就是so庫。

注意:因為用的谷歌原生so庫,所以SerialPort類的包名一定要是android_serialport_api,如果想修改這個包名,就需要重新生成對應的so庫

 

這是SerialPort類,裡面的open和close方法在報錯,這個不用管。

2、在build.gradle中新增如下程式碼: 

 


sourceSets {
            main { jni.srcDirs = [] }
        }123

3、這樣就可以串列埠通訊了 
這是串列埠操作類:

 

package utils;

import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android_serialport_api.SerialPort;

/**
 * Created by WangChaowei on 2017/12/7.
 */

public class SerialPortUtils {

    private final String TAG = "SerialPortUtils";
    private String path = "/dev/ttyS1";
    private int baudrate = 9600;
    public boolean serialPortStatus = false; //是否開啟串列埠標誌
    public String data_;
    public boolean threadStatus; //執行緒狀態,為了安全終止執行緒

    public SerialPort serialPort = null;
    public InputStream inputStream = null;
    public OutputStream outputStream = null;
    public ChangeTool changeTool = new ChangeTool();


    /**
     * 開啟串列埠
     * @return serialPort串列埠物件
     */
    public SerialPort openSerialPort(){
        try {
                serialPort = new SerialPort(new File(path),baudrate,0);
                this.serialPortStatus = true;
                threadStatus = false; //執行緒狀態

                //獲取開啟的串列埠中的輸入輸出流,以便於串列埠資料的收發
                inputStream = serialPort.getInputStream();
                outputStream = serialPort.getOutputStream();

                new ReadThread().start(); //開始執行緒監控是否有資料要接收
        } catch (IOException e) {
            Log.e(TAG, "openSerialPort: 開啟串列埠異常:" + e.toString());
            return serialPort;
        }
        Log.d(TAG, "openSerialPort: 開啟串列埠");
        return serialPort;
    }

    /**
     * 關閉串列埠
     */
    public void closeSerialPort(){
        try {
            inputStream.close();
            outputStream.close();

            this.serialPortStatus = false;
            this.threadStatus = true; //執行緒狀態
            serialPort.close();
        } catch (IOException e) {
            Log.e(TAG, "closeSerialPort: 關閉串列埠異常:"+e.toString());
            return;
        }
        Log.d(TAG, "closeSerialPort: 關閉串列埠成功");
    }

    /**
     * 傳送串列埠指令(字串)
     * @param data String資料指令
     */
    public void sendSerialPort(String data){
        Log.d(TAG, "sendSerialPort: 傳送資料");

        try {
            byte[] sendData = data.getBytes(); //string轉byte[]
            this.data_ = new String(sendData); //byte[]轉string
            if (sendData.length > 0) {
                outputStream.write(sendData);
                outputStream.write('\n');
                //outputStream.write('\r'+'\n');
                outputStream.flush();
                Log.d(TAG, "sendSerialPort: 串列埠資料傳送成功");
            }
        } catch (IOException e) {
            Log.e(TAG, "sendSerialPort: 串列埠資料傳送失敗:"+e.toString());
        }

    }

    /**
     * 單開一執行緒,來讀資料
     */
    private class ReadThread extends Thread{
        @Override
        public void run() {
            super.run();
            //判斷程序是否在執行,更安全的結束程序
            while (!threadStatus){
                Log.d(TAG, "進入執行緒run");
                //64   1024
                byte[] buffer = new byte[64];
                int size; //讀取資料的大小
                try {
                    size = inputStream.read(buffer);
                    if (size > 0){
                        Log.d(TAG, "run: 接收到了資料:" + changeTool.ByteArrToHex(buffer));
                        Log.d(TAG, "run: 接收到了資料大小:" + String.valueOf(size));
                        onDataReceiveListener.onDataReceive(buffer,size);
                    }
                } catch (IOException e) {
                    Log.e(TAG, "run: 資料讀取異常:" +e.toString());
                }
            }

        }
    }

    //這是寫了一監聽器來監聽接收資料
    public OnDataReceiveListener onDataReceiveListener = null;
    public static interface OnDataReceiveListener {
        public void onDataReceive(byte[] buffer, int size);
    }
    public void setOnDataReceiveListener(OnDataReceiveListener dataReceiveListener) {
        onDataReceiveListener = dataReceiveListener;
    }

}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131

4、activity中只貼串列埠資料監聽事件

 

        //串列埠資料監聽事件
        serialPortUtils.setOnDataReceiveListener(new SerialPortUtils.OnDataReceiveListener() {
            @Override
            public void onDataReceive(byte[] buffer, int size) {
                Log.d(TAG, "進入資料監聽事件中。。。" + new String(buffer));
                //
                //線上程中直接操作UI會報異常:ViewRootImpl$CalledFromWrongThreadException
                //解決方法:handler
                //
                mBuffer = buffer;
                handler.post(runnable);
            }
            //開執行緒更新UI
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    textView_status.setText("size:"+ String.valueOf(mBuffer.length)+"資料監聽:"+ new String(mBuffer));
                }
            };
        });