Android 12 jni读写串口

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,“自定义字节数组”,“自定义字节数组长度”);

你可能感兴趣的:(android)