1.项目根目录下建立jni文件夹包含以下三个文件
serial.c
serial.h
Android.mk
1)serial.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "serial.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "serial-jni"
#define UNUSED(A) (void*)(A);
/**
*os.O_RDONLY: 以只读的方式打开
*os.O_WRONLY: 以只写的方式打开
*os.O_RDWR : 以读写的方式打开
*os.O_NONBLOCK: 打开时不阻塞
*os.O_APPEND: 以追加的方式打开
*os.O_CREAT: 创建并打开一个新文件
*os.O_TRUNC: 打开一个文件并截断它的长度为零(必须有写权限)
*os.O_EXCL: 如果指定的文件存在,返回错误
*os.O_SHLOCK: 自动获取共享锁
*os.O_EXLOCK: 自动获取独立锁
*os.O_DIRECT: 消除或减少缓存效果
*os.O_FSYNC : 同步写入
*os.O_NOFOLLOW: 不追踪软链接
*
*
**/
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportOpen
(JNIEnv *env, jclass cls, jstring path)
{
UNUSED(cls);
const char *c_path = (const char*)(*env)->GetStringUTFChars(env,path,JNI_FALSE);
int fd = open(c_path,O_RDWR|O_NOCTTY);
if(fd < 0){
ALOGE("fail to open %s,errno:%s",c_path,strerror(errno));
goto out;
}
if(tcflush(fd, TCIOFLUSH) < 0){
ALOGE("fail to flush uart port,errno:%s",strerror(errno));
close(fd);
goto out;
}
struct termios options;
if(tcgetattr(fd, &options) < 0){
ALOGE("fail to get port settings,errno:%s",strerror(errno));
close(fd);
goto out;
}
cfmakeraw(&options);
//options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
//options.c_oflag &= ~OPOST;
//options.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
options.c_cflag &= ~PARENB;//无校验
// options.c_cflag &= ~CSTOPB;//停止位 1位
options.c_cflag |= CS8; // 将数据位修改为8bit
options.c_cflag &= ~CRTSCTS; //无流控
cfsetospeed(&options, B115200);
cfsetispeed(&options, B115200);
if(tcsetattr(fd, TCSANOW, &options) < 0){
ALOGE("fail to set port setting,errno:%s",strerror(errno));
close(fd);
goto out;
}
ALOGE("success open coffee !");
tcflush(fd, TCIOFLUSH);
out:
(*env)->ReleaseStringUTFChars(env,path,c_path);
return fd;
}
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportRead
(JNIEnv *env, jclass cls, jint fd, jbyteArray buffer, jint length)
{
UNUSED(cls);
unsigned char *c_buf = (unsigned char*)(*env)->GetByteArrayElements(env,buffer,NULL);
int ret = read(fd,c_buf,length);
//ALOGE("read start");
if(ret<=0)
{
ALOGE("fail to read,errno:%s",strerror(errno));
}
//ALOGE("read finish");
(*env)->ReleaseByteArrayElements(env,buffer,(jbyte*)c_buf,0);
return ret;
}
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportWrite
(JNIEnv *env, jclass cls, jint fd, jbyteArray buffer, jint length)
{
UNUSED(cls);
unsigned char *c_buf = (unsigned char*)(*env)->GetByteArrayElements(env,buffer,NULL);
int ret = write(fd,c_buf,length);
(*env)->ReleaseByteArrayElements(env,buffer,(jbyte*)c_buf,0);
return ret;
}
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportClose
(JNIEnv *env, jclass cls, jint fd)
{
UNUSED(env);
UNUSED(cls);
return close(fd);
}
2)serial.h
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "serial.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "serial-jni"
#define UNUSED(A) (void*)(A);
/**
*os.O_RDONLY: 以只读的方式打开
*os.O_WRONLY: 以只写的方式打开
*os.O_RDWR : 以读写的方式打开
*os.O_NONBLOCK: 打开时不阻塞
*os.O_APPEND: 以追加的方式打开
*os.O_CREAT: 创建并打开一个新文件
*os.O_TRUNC: 打开一个文件并截断它的长度为零(必须有写权限)
*os.O_EXCL: 如果指定的文件存在,返回错误
*os.O_SHLOCK: 自动获取共享锁
*os.O_EXLOCK: 自动获取独立锁
*os.O_DIRECT: 消除或减少缓存效果
*os.O_FSYNC : 同步写入
*os.O_NOFOLLOW: 不追踪软链接
*
*
**/
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportOpen
(JNIEnv *env, jclass cls, jstring path)
{
UNUSED(cls);
const char *c_path = (const char*)(*env)->GetStringUTFChars(env,path,JNI_FALSE);
int fd = open(c_path,O_RDWR|O_NOCTTY);
if(fd < 0){
ALOGE("fail to open %s,errno:%s",c_path,strerror(errno));
goto out;
}
if(tcflush(fd, TCIOFLUSH) < 0){
ALOGE("fail to flush uart port,errno:%s",strerror(errno));
close(fd);
goto out;
}
struct termios options;
if(tcgetattr(fd, &options) < 0){
ALOGE("fail to get port settings,errno:%s",strerror(errno));
close(fd);
goto out;
}
cfmakeraw(&options);
//options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
//options.c_oflag &= ~OPOST;
//options.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
options.c_cflag &= ~PARENB;//无校验
// options.c_cflag &= ~CSTOPB;//停止位 1位
options.c_cflag |= CS8; // 将数据位修改为8bit
options.c_cflag &= ~CRTSCTS; //无流控
cfsetospeed(&options, B115200);
cfsetispeed(&options, B115200);
if(tcsetattr(fd, TCSANOW, &options) < 0){
ALOGE("fail to set port setting,errno:%s",strerror(errno));
close(fd);
goto out;
}
ALOGE("success open coffee !");
tcflush(fd, TCIOFLUSH);
out:
(*env)->ReleaseStringUTFChars(env,path,c_path);
return fd;
}
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportRead
(JNIEnv *env, jclass cls, jint fd, jbyteArray buffer, jint length)
{
UNUSED(cls);
unsigned char *c_buf = (unsigned char*)(*env)->GetByteArrayElements(env,buffer,NULL);
int ret = read(fd,c_buf,length);
//ALOGE("read start");
if(ret<=0)
{
ALOGE("fail to read,errno:%s",strerror(errno));
}
//ALOGE("read finish");
(*env)->ReleaseByteArrayElements(env,buffer,(jbyte*)c_buf,0);
return ret;
}
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportWrite
(JNIEnv *env, jclass cls, jint fd, jbyteArray buffer, jint length)
{
UNUSED(cls);
unsigned char *c_buf = (unsigned char*)(*env)->GetByteArrayElements(env,buffer,NULL);
int ret = write(fd,c_buf,length);
(*env)->ReleaseByteArrayElements(env,buffer,(jbyte*)c_buf,0);
return ret;
}
JNIEXPORT jint JNICALL Java_com_mmi_factorykit_serial_SerialController_serialportClose
(JNIEnv *env, jclass cls, jint fd)
{
UNUSED(env);
UNUSED(cls);
return close(fd);
}
3)Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := serial.c
LOCAL_MODULE:= libSerial
LOCAL_MULTILIB := 64
LOCAL_PRELINK_MODULE := false
LOCAL_HEADER_LIBRARIES := jni_headers
LOCAL_SHARED_LIBRARIES := liblog libcutils
include $(BUILD_SHARED_LIBRARY)
LOCAL_HEADER_LIBRARIES := jni_headers在Android10之前的版本不需要加12中不加会报错找不到#include
2.注意c和.h文件中的函数名Java_com_mmi_factorykit_serial_SerialController_serialportOpen为例
创建java文件目录就为com\mmi\factorykit\serial\SerialController.java
3.SerialController.java
public class SerialController{
static {
System.loadLibrary("Serial");
}
private MmiDeviceManager ldm;
public static native int serialportOpen(String path);
public static native int serialportRead(int fd, byte[] buffer, int length);
public static native int serialportWrite(int fd, byte[] buffer, int length);
public static native int serialportClose(int fd);
}
4.serialportOpen(“dev/ttyhs1”);打开串口
int mfd=serialportOpen(“dev/ttyhs1”);//串口句柄 读写串口时需要
serialportRead(mfd,“自定义字节数组”,“自定义字节数组长度”);