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();
            }
        });
    }
相关推荐
飞猿_SIR43 分钟前
Android Exoplayer 实现多个音视频文件混合播放以及音轨切换
android·音视频
HumoChen991 小时前
GZip+Base64压缩字符串在ios上解压报错问题解决(安卓、PC模拟器正常)
android·小程序·uniapp·base64·gzip
沙振宇5 小时前
【HarmonyOS】ArkTS开发应用的横竖屏切换
android·华为·harmonyos
橙子199110167 小时前
Kotlin 中的作用域函数
android·开发语言·kotlin
zimoyin7 小时前
Kotlin 懒初始化值
android·开发语言·kotlin
枣伊吕波8 小时前
第六节第二部分:抽象类的应用-模板方法设计模式
android·java·设计模式
萧然CS8 小时前
使用ADB命令操作Android的apk/aab包
android·adb
_extraordinary_12 小时前
MySQL 事务(二)
android·数据库·mysql
鸿蒙布道师16 小时前
鸿蒙NEXT开发动画案例5
android·ios·华为·harmonyos·鸿蒙系统·arkui·huawei
橙子1991101621 小时前
在 Kotlin 中什么是委托属性,简要说说其使用场景和原理
android·开发语言·kotlin