1.去github 搜索 AndroidSerial 看看别人的用例就行了.不过一般是google 项目翻写过来的.
2.去下载看看文档 链接
3.我的代码
#include <pthread.h>
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/serial_core.h>
#include <android/bitmap.h>
#include <jni.h>
#include "SerialPort.h"
#include <sys/ioctl.h>
#include <malloc.h>
#include "android/log.h"
static const char *TAG = "serial_port";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
#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)
int pos[] = {128, 64, 32, 16, 8, 4, 2, 1};
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
const jbyte data[1];
void jniThrowException(JNIEnv *pEnv, const char *, const char *);
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: android_serialport_SerialPort
* Method: open
* Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
* rrrr
* uuuu
*/JNIEXPORT jobject JNICALL Java_android_1serialport_1api_SerialPort_open(
JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags) {
int fd;
speed_t speed;
jobject mFileDescriptor;
/* Check arguments */
{
speed = getBaudrate(baudrate);
if (speed == -1) {
LOGE("Invalid baudrate");
return NULL;
}
}
{
jboolean iscopy;
const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
LOGD("Opening serial port %s with flags 0x%x",
path_utf, O_RDWR | 0);
fd = open(path_utf, O_RDWR | O_NOCTTY | O_SYNC, S_IRWXU);
LOGD("open() fd = %d", fd);
(*env)->ReleaseStringUTFChars(env, path, path_utf);
if (fd == -1) {
LOGE("Cannot open port");
return NULL;
}
LOGI("sync %d:", sync);
}
/* Configure device */
{
struct termios cfg;
LOGD("Configuring serial port");
if (tcgetattr(fd, &cfg)) {
LOGE("tcgetattr() failed");
close(fd);
return NULL;
}
cfmakeraw(&cfg);
cfsetispeed(&cfg, speed);
cfsetospeed(&cfg, speed);
cfg.c_cflag |= CREAD | CLOCAL;
cfg.c_cc[VMIN] = 0;
cfg.c_cc[VTIME] = 0;
if (flags == 1) {
cfg.c_cflag &= ~CRTSCTS;
cfg.c_iflag |= IXON | IXOFF | IXANY;
LOGE("IXON flow control open");
} else if (flags == 2) {
cfg.c_iflag &= ~(IXON | IXOFF | IXANY);
cfg.c_cflag |= CRTSCTS;
LOGE("CRTSCTS flow control open");
} else {
cfg.c_cflag &= ~CRTSCTS;
cfg.c_iflag &= ~(IXON | IXOFF | IXANY);
LOGE("flow control not open");
}
if (tcsetattr(fd, TCSANOW, &cfg)) {
LOGE("tcsetattr() failed");
close(fd);
/* TODO: throw an exception */
return NULL;
}
}
/* Create a corresponding file descriptor */
{
jclass cFileDescriptor = (*env)->FindClass(env,
"java/io/FileDescriptor");
jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor,
"<init>", "()V");
jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor,
"descriptor", "I");
mFileDescriptor = (*env)->NewObject(env, cFileDescriptor,
iFileDescriptor);
(*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint) fd);
}
struct serial_struct serial;
ioctl(fd, TIOCGSERIAL, &serial);
LOGE("波特率 %d", serial.baud_base);
LOGE("访问方式 %d", serial.io_type);
LOGE("串口几 %d", serial.port);
LOGE("等待时长 %d", serial.closing_wait);
LOGE("基地址 %d", serial.iomem_base);
LOGE("缓冲区 %d", serial.xmit_fifo_size);
/* serial.xmit_fifo_size = 4096;
int success= ioctl(fd, TIOCSSERIAL, &serial);
LOGI("是否成功 %d",success);*/
int success = pthread_mutex_init(&mutex, NULL);
LOGI("是否成功 %d", success);
return mFileDescriptor;
}
/*
* Class: cedric_serial_SerialPort
* Method: close
* Signature: ()V
*/JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_close(
JNIEnv *env, jobject thiz) {
jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
jclass FileDescriptorClass = (*env)->FindClass(env,
"java/io/FileDescriptor");
jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd",
"Ljava/io/FileDescriptor;");
jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass,
"descriptor", "I");
jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
LOGD("close(fd = %d)", descriptor);
pthread_mutex_destroy(&mutex);
close(descriptor);
}
/*
* *TCIFLUSH 清除输入队列 0
*TCOFLUSH 清除输出队列 1
*TCIOFLUSH 清除输入、输出队列 2
*
* */
JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_flush(JNIEnv *env, jobject thiz,
jint flag) {
jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
jclass FileDescriptorClass = (*env)->FindClass(env,
"java/io/FileDescriptor");
jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd",
"Ljava/io/FileDescriptor;");
jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass,
"descriptor", "I");
jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
tcflush(descriptor, flag);
LOGI("flush", "清空" + flag);
}
JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_tcDrain(JNIEnv *env, jobject thiz) {
jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
jclass FileDescriptorClass = (*env)->FindClass(env,
"java/io/FileDescriptor");
jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd",
"Ljava/io/FileDescriptor;");
jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass,
"descriptor", "I");
jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
int i = tcdrain(descriptor);
LOGE("直到数据 % d:", i);
}
/**
* TCIOFF
Transmit a STOP character, intended to suspend input data.
TCION
Transmit a START character, intended to restart input data.
TCOOFF
Suspend output.
TCOON
Restart output.
*/
JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_tcFlow(JNIEnv *env, jobject
thiz, jint flag) {
jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
jclass FileDescriptorClass = (*env)->FindClass(env,
"java/io/FileDescriptor");
jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd",
"Ljava/io/FileDescriptor;");
jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass,
"descriptor", "I");
jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
int i = tcflow(descriptor, flag);
LOGE("tcflow % d:", i);
}
JNIEXPORT jint JNICALL Java_android_1serialport_1api_SerialPort_write
(JNIEnv *env, jclass thiz, jint fd, jbyteArray cmd, jint offset, jint size) {
pthread_mutex_lock(&mutex);
jbyte *data = (*env)->GetByteArrayElements(env, cmd, NULL);
int send = write(fd, data, size);
(*env)->ReleaseByteArrayElements(env, cmd, data, 0);
if (send<0){
jniThrowException(env,
"java/io/IOException", NULL);
}
// (*env)->DeleteLocalRef(env, data);
pthread_mutex_unlock(&mutex);
return send;
}
JNIEXPORT jint JNICALL Java_android_1serialport_1api_SerialPort_read
(JNIEnv *env, jclass thiz, jint fd, jbyteArray cmd, jint offset, jint size) {
pthread_mutex_lock(&mutex);
jbyte *buf = (jbyte *) malloc(size);
if (!buf) {
jniThrowException(env,
"java/lang/OutOfMemoryError", NULL);
return -1;
}
int ret = read(fd, buf, size);
if (ret > 0) {
(*env)->SetByteArrayRegion(env,cmd,
0, ret, buf);
}
free(buf);
if (ret < 0) {
jniThrowException(env,
"java/io/IOException", NULL);
}
// (*env)->DeleteLocalRef(env, data);
pthread_mutex_unlock(&mutex);
return ret;
}
JNIEXPORT jint JNICALL Java_android_1serialport_1api_SerialPort_getInfo
(JNIEnv *env, jclass thiz, jint fd) {
struct serial_icounter_struct info;
ioctl(fd, TIOCGICOUNT, &info);
LOGE("打印接收 =%d", info.tx);
LOGE("打印发送 =%d", info.rx);
LOGE("打印发送溢出 =%d", info.overrun);
LOGE("数据溢出 =%d", info.buf_overrun);
LOGE("中断计数 =%d", info.brk);
LOGE("frame =%d", info.frame);
LOGE("反转 =%d", info.reserved);
LOGE("cts =%d", info.cts);
LOGE("dsr =%d", info.dsr);
return info.tx;
}
void jniThrowException(JNIEnv *pEnv, const char *throwName, const char *message) {
jclass throwClass = (*pEnv)->FindClass(pEnv,throwName);
if (throwClass) {
return;
}
( *pEnv)->ThrowNew(pEnv,throwClass, message);
}
ps:注意的一些地方.1.死锁 2.在读之前先用flush 清除未读出的数据 在发送打印机状态指令之后先延迟 几十毫秒后在读.3.用户反映硬流控不能用 ,但是这代码在linux 系统上能用.4.可以将fd 变量缓存起来6.使用write 方法可以将一个一个字节的传,你使用FileOutputStream.write 方法里面也是一个一个字节的传的;