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();
            }
        });
    }
相关推荐
潘潘潘14 分钟前
Android多线程机制简介
android
CYRUS_STUDIO2 小时前
利用 Linux 信号机制(SIGTRAP)实现 Android 下的反调试
android·安全·逆向
CYRUS_STUDIO2 小时前
Android 反调试攻防实战:多重检测手段解析与内核级绕过方案
android·操作系统·逆向
黄林晴6 小时前
如何判断手机是否是纯血鸿蒙系统
android
火柴就是我6 小时前
flutter 之真手势冲突处理
android·flutter
法的空间6 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
循环不息优化不止7 小时前
深入解析安卓 Handle 机制
android
恋猫de小郭7 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
jctech7 小时前
这才是2025年的插件化!ComboLite 2.0:为Compose开发者带来极致“爽”感
android·开源
用户2018792831677 小时前
为何Handler的postDelayed不适合精准定时任务?
android