前几天公司有通过搭载Android系统的开发板来使用打卡机统计数据的需求,对于攻城狮来说就需要在Android平台上读写打卡机的串口,在网上搜索一些东西之后发现了在google code 上的android serial port api可以用,墙了之后拿到源码发现还有demo,不错不错,我这个帖子就通过serial port api的源码简单得实现一个读写串口,这个当然是在native写的,如果还有哪些童鞋不清楚android上使用jni和native的话可以跳转到我的上篇帖子点我点我


在Android工程中建立一个工具类,该类的作用就是通过调用Jni中声明的Native方法openSerialPort,来打开参数中path的串口,该串口的具体参数为:baudrate比特率,databits数据位,stopbits停止位,和parity奇偶校验.如果打开成功的话该方法会返回path串口的文件描述实例,这样就可以获取到能读写该串口的IO流,串口对于我们来说就可以当成一个文件(在linux系统上确实是一个设备文件).成功就按按着不同的命令或数据协议R/W串口就OK了.

/** * @Title: SerialPortUtil.java * @Description: the util of serial port * @author Jesse   * @date Nov 21, 2014 10:10:49 AM * @version V1.0   */public class SerialPortUtil {private final String TAG = SerialPortUtil.class.getSimpleName();private static SerialPortUtil mInstance = null;private StudioJni studioJni = StudioJni.getInstance();private FileDescriptor mFd;private FileInputStream mFileInputStream = null; private FileOutputStream mFileOutputStream = null; private boolean isRunning = false;public static SerialPortUtil getInstance(){if(mInstance == null){mInstance = new SerialPortUtil();}return mInstance;}public boolean openSerialPort(String path,int baudrate,int databits, int stopbits, char parity){Log.i(TAG, "openSerialPort,path:" + path + " ,baudrate:" + baudrate + " ,databits:" +databits+ " ,stopbits:" + stopbits + " ,parity:" + parity);if(isRunning){Log.i(TAG, "openSerialPort,the serial port is running");return false;}mFd = studioJni.serialPortOpen(path, baudrate,databits,stopbits,parity);if(mFd != null){isRunning = true;mFileInputStream = new FileInputStream(mFd);      mFileOutputStream = new FileOutputStream(mFd); }else{Log.i(TAG, "openSerialPort," + "the deivce is null");}return isRunning;}public void closeSerialPort(){Log.i(TAG, "closeSerialPort");studioJni.serialPortClose();isRunning = false;}public InputStream getInputStream() {      return mFileInputStream;  }    public OutputStream getOutputStream() {      return mFileOutputStream;  }  }
在Native实现中,就是拿着配置下来的参数来打开串口,配置串口.成功了就返回一个java的文件描述,失败返回空.

JNIEXPORT jobject JNICALL serial_port_open(JNIEnv *env,jclass thiz,jstring path, jint baudrate,                                           jint databits,jint stopbits,jchar parity){    LOGI(CAMERA_TAG,"serial_port_open");    int fd;    speed_t speed;    jobject mFileDescriptor;    /* Check arguments */    {        speed = getBaudrate(baudrate);        if (speed == -1) {            /* TODO: throw an exception */            LOGI(CAMERA_TAG,"serial_port_open,Invalid baudrate");            LOGE(CAMERA_TAG,"serial_port_open,Invalid baudrate");            return NULL;        }    }    /* Opening device */    {        jboolean iscopy;        const char *path_utf = env -> GetStringUTFChars(path, &iscopy);        LOGI(CAMERA_TAG,"serial_port_open,Opening serial port %s with flags 0x%x", path_utf, O_RDWR);        fd = open(path_utf, O_RDWR);        LOGI(CAMERA_TAG,"serial_port_open,open() fd = %d", fd);        env->ReleaseStringUTFChars(path, path_utf);        if (fd == -1)        {            /* Throw an exception */            LOGI(CAMERA_TAG,"serial_port_open,Cannot open port");            LOGE(CAMERA_TAG,"serial_port_open","Cannot open port");            /* TODO: throw an exception */            return NULL;        }    }    /* Configure device */    {        struct termios cfg;        LOGI(CAMERA_TAG,"serial_port_open,Configuring serial port");        if (tcgetattr(fd, &cfg))        {            LOGI(CAMERA_TAG,"serial_port_open,tcgetattr() failed");            LOGE(CAMERA_TAG,"serial_port_open","tcgetattr() failed");            close(fd);            /* TODO: throw an exception */            return NULL;        }        cfmakeraw(&cfg);        cfsetispeed(&cfg, speed);        cfsetospeed(&cfg, speed);        if (tcsetattr(fd, TCSANOW, &cfg))        {            LOGI(CAMERA_TAG,"serial_port_open","tcsetattr() failed");            LOGE(CAMERA_TAG,"serial_port_open","tcsetattr() failed");            close(fd);            /* TODO: throw an exception */            return NULL;        }        set_Parity(fd, databits, stopbits, parity);        FD = fd;    }    /* Create a corresponding file descriptor */    {        jclass cFileDescriptor = env->FindClass("java/io/FileDescriptor");        jmethodID iFileDescriptor = env->GetMethodID(cFileDescriptor, "<init>", "()V");        jfieldID descriptorID = env->GetFieldID(cFileDescriptor, "descriptor", "I");        mFileDescriptor = env->NewObject(cFileDescriptor, iFileDescriptor);        env->SetIntField(mFileDescriptor, descriptorID, (jint)fd);    }    return mFileDescriptor;}




更多相关文章

  1. Android高手进阶教程(二十三)之---Android中的日历读写操作!!!
  2. Android读写XML(中)——SAX
  3. Android(安卓)Input系统添加自定义键值上报实现(from Linux to A
  4. android下变态的串口通讯
  5. Android高手进阶教程(二十三)之---Android中的日历读写操作!!!
  6. Android读写XML(中)——SAX
  7. Android的NDK开发(5)————Android(安卓)JNI层实现文件的read
  8. Android数据持久化——五种方式
  9. 《Android开发从零开始》——25.数据存储(4)

随机推荐

  1. Linux中shell脚本使用
  2. 你真知道如何高效用mapPartitions吗?
  3. spark streaming窗口及聚合操作后如何管
  4. 关于浪尖小蜜圈的一些说明
  5. 浪尖聊聊大数据从业者的迷茫及解决方案
  6. Phpstorm激活码,更新于2021年3月15日
  7. CocosCreator发布web-desktop获取本地资
  8. 干饭人表情包使用nodejs实现
  9. 目前高效的前端开发工具分享给你
  10. 面试官再问你优先级队列,请把这篇文章丢给