Android串口通信

最近因为需要在Android平台进行电子秤的开发,首先第一步就是需要解决Android串口通信获取电子秤的称重信息。

google官方给我们提供了现成的解决方案,里面有编译好的apk文件还有源代码可以直接参考使用。地址:http://code.google.com/p/android-serialport-api/

但是上面的地址国内屏蔽了。如果不方便访问,也可以在国内的gitee等开源社区找到fock的项目进行下载,或者是通过百度搜索google android-serialport-api找到。

拿到工业用的电子秤等设备的第一步,就是要熟悉一下它的通信协议。一般这些设备都会提供类似RS232或者module bus等串口通信协议,不同的厂家不同的设备串口协议不同,需要联系厂家,仔细阅读各类设备的通信协议。熟悉通信协议之后,可以结合一些串口调试工具进行调试,测试通过之后就可以写代码实现功能了。

下面就直接演示在Android当中,串口通信的用法步骤:

1. 加载编译好的so包

完全可以下载c源码,自行编译产生so包。但是直接引用编译好的so包能节约大量的时间,这个可以直接搜索下载。

需要说明的是,要先注意查看一下目标设备的Android平台,可以通过adb shell登录后输入一下命令查看:

bash 复制代码
adb shell getprop ro.product.cpu.abi

这条命令会返回设备的主架构,例如 arm64-v8a、armeabi-v7a、x86 等等。我们的so包就应该与之对应。

如下:

2. 准备Android串口通信的助手类

google的示范项目中有现成的源代码,可以直接复制到项目中使用。

要注意的是项目中,要建立与google项目中一样的包名 android_serialport_api,否则会报错找不到类。

SerialPort :

java 复制代码
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;

    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;
    }

    /**************************************modify start********************************************/
    public void closeStream() {
        try {
            if (null != mFileOutputStream) {
                mFileOutputStream.close();
                mFileOutputStream = null;
            }
            if (null != mFileInputStream) {
                mFileInputStream.close();
                mFileInputStream = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**************************************modify end********************************************/
    // JNI
    private native static FileDescriptor open(String path, int baudrate, int flags);

    public native void close();

    static {
        System.loadLibrary("serial_port");
    }

}

SerialPortFinder :

java 复制代码
public class SerialPortFinder {
    public class Driver {
        public Driver(String name, String root) {
            mDriverName = name;
            mDeviceRoot = root;
        }
        private String mDriverName;
        private String mDeviceRoot;
        Vector<File> mDevices = null;
        public Vector<File> getDevices() {
            if (mDevices == null) {
                mDevices = new Vector<File>();
                File dev = new File("/dev");
                File[] files = dev.listFiles();
                int i;
                for (i=0; i<files.length; i++) {
                    if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
                        Log.d(TAG, "Found new device: " + files[i]);
                        mDevices.add(files[i]);
                    }
                }
            }
            return mDevices;
        }
        public String getName() {
            return mDriverName;
        }
    }

    private static final String TAG = "SerialPort";

    private Vector<Driver> mDrivers = null;

    Vector<Driver> getDrivers() throws IOException {
        if (mDrivers == null) {
            mDrivers = new Vector<Driver>();
            LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
            String l;
            while((l = r.readLine()) != null) {
                // Issue 3:
                // Since driver name may contain spaces, we do not extract driver name with split()
                String drivername = l.substring(0, 0x15).trim();
                String[] w = l.split(" +");
                if ((w.length >= 5) && (w[w.length-1].equals("serial"))) {
                    Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length-4]);
                    mDrivers.add(new Driver(drivername, w[w.length-4]));
                }
            }
            r.close();
        }
        return mDrivers;
    }

    public String[] getAllDevices() {
        Vector<String> devices = new Vector<String>();
        // Parse each driver
        Iterator<Driver> itdriv;
        try {
            itdriv = getDrivers().iterator();
            while(itdriv.hasNext()) {
                Driver driver = itdriv.next();
                Iterator<File> itdev = driver.getDevices().iterator();
                while(itdev.hasNext()) {
                    String device = itdev.next().getName();
                    String value = String.format("%s (%s)", device, driver.getName());
                    devices.add(value);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return devices.toArray(new String[devices.size()]);
    }

    public String[] getAllDevicesPath() {
        Vector<String> devices = new Vector<String>();
        // Parse each driver
        Iterator<Driver> itdriv;
        try {
            itdriv = getDrivers().iterator();
            while(itdriv.hasNext()) {
                Driver driver = itdriv.next();
                Iterator<File> itdev = driver.getDevices().iterator();
                while(itdev.hasNext()) {
                    String device = itdev.next().getAbsolutePath();
                    devices.add(device);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return devices.toArray(new String[devices.size()]);
    }
}

3. 项目中进行串口通信的开发

主要示例代码如下:

  • 发送串口
java 复制代码
private void sendData(String data) {
        try {
            // 打开串口
            mSerialPort = new SerialPort(
                    new File("/dev/ttyS3"),
                    9600, // 波特率// 校验位(0=NONE)
                    0
            );
            mOutputStream = mSerialPort.getOutputStream();
        } catch (SecurityException | IOException e) {
            e.printStackTrace();
        }

        if (mOutputStream != null) {
            try {
                // 将字符串转换为字节数组并发送
                mOutputStream.write(data.getBytes());
                mInputStream = mSerialPort.getInputStream();

                new ReadThread().start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • 线程操作
java 复制代码
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;
                }
            }
        }
    }
  • UI回显
java 复制代码
void onDataReceived(final byte[] buffer, final int size) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                String msg = new String(buffer, 0, buffer.length);
                Log.i("gw", msg);
                mTextView.append(msg);

//                //断开串口连接
//                mSerialPort.close();
            }
        });
    }
相关推荐
鸿蒙布道师6 分钟前
鸿蒙NEXT开发权限工具类(申请授权相关)(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师8 分钟前
鸿蒙NEXT开发定位工具类 (WGS-84坐标系)(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
alexhilton1 小时前
深入理解Jetpack Compose中的函数的执行顺序
android·kotlin·android jetpack
李新_2 小时前
Android 画中画避坑指北
android
一一Null3 小时前
Android studio—socketIO库return与emit的使用
android·java·网络·ide·websocket·网络协议·android studio
ansondroider4 小时前
Android RK356X TVSettings USB调试开关
android·adb·usb·otg·rk356x
jiaxingcode4 小时前
MAC系统下完全卸载Android Studio
android·macos·android studio
张力尹4 小时前
「架构篇 1」认识 MVC / MVP / MVVM / MVI
android·面试·架构
张力尹4 小时前
「架构篇 2」认识 MVC / MVP / MVVM / MVI
android·面试·架构