2020 android 设备串口 通讯 监听 开发 (测试)

环境:android studio3.5 , java8 , 串口通讯设备(刷卡机)一台

场景:android系统(非手机)的设备上外接一个刷卡机,读取卡号

介绍:android 实现设备的刷卡操作 监听 、处理(打印卡号)。(参考 google 官方demo)

android studio 先连接设备, adb connect 设备ip:端口

1 引入 

 权限:

    <uses-feature android:name="android.hardware.nfc" android:required="true"/> <uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.RECORD_AUDIO"/>

 包:

implementation 'com.aill:AndroidSerialPort:1.0.8'
implementation files('libs/eventbus-3.0.0.jar')

2 复制 。目录结构如下(目录结构还得按照官方的路径),package com.aill.androidserialport;

 

(1)SerialPort
package com.aill.androidserialport;

import android.text.TextUtils;
import android.util.Log;
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;

/**
 * @description 串口操作类
 */
public class SerialPort {

    private static final String TAG = "SerialPort";
    /**
     * 不要删除或重命名字段mFd:原生方法close()使用了该字段
     */
    private FileDescriptor mFd;
    private FileInputStream mFileInputStream;
    private FileOutputStream mFileOutputStream;
    /**
     * 有些设备su路径是/system/xbin/su
     */
    private static String mSuPath = "/system/bin/su";
    static {
        System.loadLibrary("android_serial_port");
    }
    public static void setSuPath(String suPath) {
        if (TextUtils.isEmpty(suPath)) {
            return;
        }
        mSuPath = suPath;
    }
    public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
        /* 检查访问权限 */
        if (!device.canRead() || !device.canWrite()) {
            try {
                /* 没有读/写权限,尝试对文件进行提权 */
                Process su = Runtime.getRuntime().exec(mSuPath);
                String cmd = "chmod 777 " + 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.i(TAG, "open() return null");
            throw new IOException();
        }
        mFileInputStream = new FileInputStream(mFd);
        mFileOutputStream = new FileOutputStream(mFd);
    }
    /**
     * 打开串口
     *
     * @param path     设备路径
     * @param baudrate 波特率
     * @param flags
     * @return FileDescriptor
     */
    private native static FileDescriptor open(String path, int baudrate, int flags);
    /**
     * 关闭串口
     */
    public native void close();
    public InputStream getInputStream() {
        return mFileInputStream;
    }
    public OutputStream getOutputStream() {
        return mFileOutputStream;
    }
}
(2)SerialPortUtil
package com.aill.androidserialport;

import android.util.Log;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class SerialPortUtil {
    private static SerialPort serialPort = null;
    private static InputStream inputStream = null;
    private static OutputStream outputStream = null;
    private static ReceiveThread mReceiveThread = null;
    private static boolean isStart = false;
    /**
     * 打开串口,接收数据
     * 通过串口,接收单片机发送来的数据
     */
    public static void openSerialPort(String tty, int baudRate, int flags) {
        try {
            serialPort = new SerialPort(new File(tty), baudRate, flags);
            //调用对象SerialPort方法,获取串口中"读和写"的数据流
            inputStream = serialPort.getInputStream();
            outputStream = serialPort.getOutputStream();
            isStart = true;

        } catch (IOException e) {
            e.printStackTrace();
        }
        getSerialPort();
    }
    /**
     * 关闭串口
     * 关闭串口中的输入输出流
     */
    public static void closeSerialPort() {
        Log.i("close", "关闭串口");
        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 = ByteUtil.hexStringToByteArray(data);
            outputStream.write(sendData);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static void getSerialPort() {
        if (mReceiveThread == null) {
            mReceiveThread = new ReceiveThread();
        }
        mReceiveThread.start();
    }

    /**
     * 接收串口数据的线程
     */
    private static class ReceiveThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (isStart) {
                if (inputStream == null) {
                    return;
                }
                try {
                    byte[] readData = new byte[inputStream.available()];
                    int size = inputStream.read(readData);
                    if (size > 0) {
                        String readString = ByteUtil.hexBytesToString(readData);
                        EventBus.getDefault().post(readString);
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

(3)ByteUtil

package com.aill.androidserialport;

public class ByteUtil {
    private static char[] hexArray = "0123456789ABCDEF".toCharArray();
    /**
     * 字符串转字节数组
     * @param s 字符串
     * @return 数组
     */
    public static byte[] hexStringToByteArray(String s) {
        if (s.length() < 2) {
            s = "0" + s;
        }
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }
    /**
     * 字节数组转字符串
     * @param hexBytes 数组
     * @return 字符串
     */
    public static String hexBytesToString(byte[] hexBytes) {
        char[] hexChars = new char[hexBytes.length * 2];
        for (int j = 0; j < hexBytes.length; j++) {
            int v = hexBytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
    /**
     * 16进制字符串转int
     * @param hexString 字符串
     * @return int
     */
    public static int hexStringToInt(String hexString) {
        return Integer.parseInt(hexString, 16);
    }
    /**
     * 16进制字符串转byte数组
     * @param hexString the hex string
     * @return byte[]
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    /**
     * char转换位byte
     * @param c char
     * @return byte
     */
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
}

3 串口测试。(这里有两点很重要:物理设备的串口 ,物理设备的波特率)

物理设备的串口:这里是串口3,所以第一个参数为 "/dev/ttyS3" ,物理设备的波特率:xxxx , 这些信息需要物理设备的厂商确认

(1)在 MainActivity 的 onCreate()下
SerialPortUtil.openSerialPort("/dev/ttyS3" , xxxx , 0);

EventBus.getDefault().register(this);

(2)在 MainActivity 下

@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void receiveStudentEventBus(String card){
   System.out.println(card);
 
}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值