Android 利用JNI实现串口通信

转载请注明出处:http://blog.csdn.net/a512337862/article/details/76035464

其实关于Android的串口通信Google早已提供了一个开源的工具,具体地址如下:https://github.com/cepr/android-serialport-api,大家可以自行下载。但是本人觉得这个demo有点过于复杂,所以在这个demo的基础上进行了一些封装,方便大家使用,勉强算得上是一个工具类。

串口操作

对于Android串口操作,基本上就是对应串口文件的读写,所以基本思路就是:
1.对串口文件进行配置(波特率等),打开串口文件
2.读写串口
3.关闭串口文件
但是这里需要注意的是Android/Java中读写串口需要用到FileDescriptor类(文件描述符),具体的大家可以参考:http://blog.csdn.net/morningsun1990/article/details/19639583

代码分析

JNI

因为本篇是基于android-serialport-api 的,JNI自然是无法跳过的坑,至于JNI如何使用,网上的教程多不胜数,这里也不班门弄斧了,可以自行上网搜索。这里提醒一下大家注意下面这点:

  • 不同的项目,包含native方法的类对应的路径一般都不相同,所以通过javah -jni指令生成的.h文件名以及方法名也不同,那对应的.c文件方法名以及包含的.h头文件也需要修改。例如,android-serialport-api中的.h文件生成的方法名如下:

这里写图片描述

但是我这边的.h中的方法名则是:
这里写图片描述

下面贴一下跟JNI层相关的代码:

.c文件

//
// Created by ZhangHao on 2016/7/29.
//
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <jni.h>

#include <android/log.h>

#include "com_serialPort_SerialPort.h"

static const char *TAG = "serial_port";
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)

static speed_t getBaudrate(jint baudrate) {
    switch (baudrate) {
        case 0:
            return B0;
        case 50:
            return B50;
        case 75:
            return B75;
        case 110:
            return B110;
        case 134:
            return B134;
        case 150:
            return B150;
        case 200:
            return B200;
        case 300:
            return B300;
        case 600:
            return B600;
        case 1200:
            return B1200;
        case 1800:
            return B1800;
        case 2400:
            return B2400;
        case 4800:
            return B4800;
        case 9600:
            return B9600;
        case 19200:
            return B19200;
        case 38400:
            return B38400;
        case 57600:
            return B57600;
        case 115200:
            return B115200;
        case 230400:
            return B230400;
        case 460800:
            return B460800;
        case 500000:
            return B500000;
        case 576000:
            return B576000;
        case 921600:
            return B921600;
        case 1000000:
            return B1000000;
        case 1152000:
            return B1152000;
        case 1500000:
            return B1500000;
        case 2000000:
            return B2000000;
        case 2500000:
            return B2500000;
        case 3000000:
            return B3000000;
        case 3500000:
            return B3500000;
        case 4000000:
            return B4000000;
        default:
            return -1;
    }
}

/*
 * Class:     com_sona_utils_SerialPort
 * Method:    open
 * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
 */

JNIEXPORT jobject JNICALL Java_com_serialPort_SerialPort_open
        (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags) {
       LOGE("JNI START");
    int fd;
    speed_t speed;
    jobject mFileDescriptor;
    /* Check arguments */
    {
        speed = getBaudrate(baudrate);
        if (speed == -1) {
            /* TODO: throw an exception */
            LOGE("Invalid baudrate");
            return NULL;
        }
    }

    /* Opening device */
    {
        jboolean iscopy;
        const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
        LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);
        fd = open(path_utf, O_RDWR | O_NOCTTY | O_NDELAY);//O_RDWR | flags
        LOGD("open() fd = %d", fd);
        (*env)->ReleaseStringUTFChars(env, path, path_utf);
        if (fd == -1) {
            /* Throw an exception */
            LOGE("Cannot open port");
            /* TODO: throw an exception */
            return NULL;
        }
        if (fcntl(fd, F_SETFL, 0) < 0)
            LOGD("fcntl failed!\n");
        else
            LOGD("fcntl=%d\n", fcntl(fd, F_SETFL, 0));
    }

    /* Configure device */
    {
        struct termios cfg;
        LOGD("Configuring serial port");
        if (tcgetattr(fd, &cfg)) {
            LOGE("tcgetattr() failed");
            close(fd);
            /* TODO: throw an exception */
            return NULL;
        }

        cfmakeraw(&cfg);
        cfg.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);


        tcflush(fd, TCIFLUSH);
        cfg.c_cc[VTIME] = 0; 
        cfg.c_cc[VMIN] = 0; //Update the Opt and do it now
        cfsetispeed(&cfg, speed);
        cfsetospeed(&cfg, speed);

        if (tcsetattr(fd, TCSANOW, &cfg)) {
            LOGE("tcsetattr() failed");
            close(fd);
            /* TODO: throw an exception */
            return NULL;
        }
    }

    
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值