1. Andorid串口开发包一般使用google多年前提供的android-serialport-api, 提供自用分支
https://github.com/zealzeng/android-serialport-api
2. Android设备一般需要root, 保证设备串口文件如/dev/ttyS0, /dev/ttyUSB0等可读可写, 如果无权限, 则需要切到su执行chmod 666。需要注意的是有些设备su路径是/system/bin/su, 有些是/system/xbin/su. 见SerialPort.java关键代码.
public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
/* Check access permission */
if (!device.canRead() || !device.canWrite()) {
Process su = null;
try {
/* Missing read/write permission, trying to chmod the file */
//su = Runtime.getRuntime().exec("/system/bin/su");
su = Runtime.getRuntime().exec("/system/xbin/su");
String cmd = "chmod 666 " device.getAbsolutePath() "n" "exitn";
su.getOutputStream().write(cmd.getBytes());
if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
throw new SecurityException();
}
}
catch (Exception e) {
e.printStackTrace();
throw new SecurityException();
}
finally {
if (su != null) {
su.destroy();
}
}
}
3. 如何确定串口文件和波特率? 可以先使用android串口工具例如Com Assistant等, 一般串口文件是/dev/ttyS**, /dev/ttyUSB**(com转USB),波特率一般连接的硬件可设置,一般是9600, 19200, 最好咨询供应商。
4. 分支自带了armeabi, armeabi-v7a, x86的libserial_port.so, 一般够用, 想玩下C的可自行build, 建议使用新些的android studio 3.3, 使用cmake比ndk make感觉方便很多, 以前c源文件找不到头文件却可编译过的bug都修复了, 追踪源码方便多了。 需要注意的是新建项目向导不再是include c support, 而是选择新的项目类型”Native C ”
修改自动生成的CMakeList.txt即可
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
serial_port
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
SerialPort.c)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
serial_port
# Links the target library to the log library
# included in the NDK.
${log-lib})
5. 串口读写阻塞设置
SerialPort.c
fd = open(path_utf, O_RDWR | flags);
Linux的open函数用于打开文件, flags一般我们传入0, 默认阻塞IO, 与Java的blocking IO一致。当日flags也可设置为O_NONBLOCK非阻塞, 与Java的NIO一致。
#ifndef O_NONBLOCK#define O_NONBLOCK 00004000#endif
一般串口的是独占的, 使用blocking IO编程会感觉简单些。
6. 串口通信协议
硬件方定义通信协议, 有些是回车换行作为分隔符, 分隔符前还有奇偶校验,笔者看到一些android串口的扩展支持设置奇偶位, 数据位和停止位, 有一些疑惑。 因为默认按照一个字节一个字节流的读法, 遇到分割符才处理, 最多额外处理奇偶校验;笔者调通的硬件不多, 期待大家指教。
switch (parity) {
case 0: break;
case 1: cfg.c_cflag |= PARENB; break;
case 2: cfg.c_cflag &= ~PARODD; break;
}
switch (dataBits) {
case 5: cfg.c_cflag |= CS5; break;
case 6: cfg.c_cflag |= CS6; break;
case 7: cfg.c_cflag |= CS7; break;
case 8: cfg.c_cflag |= CS8; break;
}
switch (stopBit) {
case 1: cfg.c_cflag &= ~CSTOPB; break;
case 2: cfg.c_cflag |= CSTOPB; break;
}
7. 串口重连
串口被拔插时应用需要支持重连,在遇到InputStream,OutputStream读取返回-1或不可能恢复的问题时, 处理串口的线程应当捕获错误, 优雅关闭当前串口资源,尝试重连,保证串口应用的健壮性。
8. Android串口消息的通知
串口通常是独占, 不能被多个android app打开, 所以很多时候android需要开一个服务, 负责监听串口消息,之后做广播到监听的app处理。
暂时用到这个度, 有问题再交流。