最近一个项目是android的系统,由于是工业产品,所以要用到串口,想着怎么去控制串口,有好些办法,最简单有效而且规范的办法就是google提供的NDK啦,其实还是蛮复杂的,因为android系统是个很花的系统,涉及到的知识面太广了。把代码贴在这,以后就不会忘了,嘎嘎.
下面是NDK部分所有的代码,需要注意的地方在最后面再讲:
/*
*Copyright 2100 Smallfish
*
*
*
*
*I love you.
*/
#include
#include
#include
#include
#include
#include
#include
#include
/*Android log
*/
#include
static const char *TAG="serialport for NFC Demo";
#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)
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;
}//end of switch
}//end of getBaudrate
/*
*Class: SerialPort
*Method: open
*Signature: (Ljava/lang/String;)V
*/
JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open
(JNIEnv *env,jobject thiz,jstring path,jint baudrate)
{
int fd;
jobject mFileDescriptor;
speed_t speed;
/*Check baudrate */
{
speed = getBaudrate(baudrate);
if(-1 == speed)
{
LOGE("Invalid baudrate passed");
return NULL;
}
}//end of check baudrate
/* Open device */
{
jboolean iscopy;
const char *path_utf = (*env)->GetStringUTFChars(env,path,&iscopy);
LOGD("Opening serial port is:%s",path_utf);
fd = open(path_utf,O_RDWR);
LOGD("opend device fd:%d",fd);
(*env)->ReleaseStringUTFChars(env,path,path_utf);
if(-1 == fd)
{
LOGD("Open serial port Failed...");
return NULL;
}
}//end of Open Device
/* Configure device*/
{
struct termios s_cfg;
if(tcgetattr(fd,&s_cfg))
{
LOGE("Get default config failed...");
return NULL;
}
cfmakeraw(&s_cfg);
cfsetispeed(&s_cfg,speed);
cfsetospeed(&s_cfg,speed);
if(tcsetattr(fd,TCSANOW,&s_cfg))
{
close(fd);
LOGE("Configure serial port failed");
return NULL;
}
}//end of Configure device
/* Create a corresponding file descriptor via opend serial port*/
{
jclass cFileDescriptor = (*env)->FindClass(env,"java/io/FileDescriptor");
jmethodID iFileDescriptor = (*env)->GetMethodID(env,cFileDescriptor,"
jfieldID descriptorID = (*env)->GetFieldID(env,cFileDescriptor,"descriptor","I");
mFileDescriptor = (*env)->NewObject(env,cFileDescriptor,iFileDescriptor);
(*env)->SetIntField(env,mFileDescriptor,descriptorID,(jint)fd);
}
return mFileDescriptor;
}//end of open
/*
* Class: serial__SerialPort
* Method: close
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_android_serialport_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","java/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 device fd:%d",descriptor);
close(descriptor);
}
需要注意的是函数名称:Java_android_serialport_SerialPort_close
分解如下:Java_这个是不变的,照写就是了,android_serialport这个是包名,这里是什么,在上层里也必须是什么,SerialPort_close这个前面部分是类名,而后面的当然就是函数名称了。
好吧:就这样,以后补上.mk文件.
下面是整个java串口类的代码,就不多说了:
package android.serialport;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;import android.util.Log;
public class SerialPort
{
private FileDescriptor mFd;
private FileInputStream mFileInputStream;
private FileOutputStream mFileOutputStream;
//这是构造函数了,是做什么的我也不知道啊
public SerialPort(File device,int baudrate) throws SecurityException,IOException
{
//open device
mFd = open(device.getAbsolutePath(),baudrate);
if(mFd == null)
{
Log.e(TAG, "native open return NULL");
throw new IOException();
}
//建立输入输出流,就可以使用这2个流来发送和接收数据了
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
}//end of SerialPort
//获取输入流
public InputStream GetInputStream()
{
return mFileInputStream;
}
//获取输出流
public OutputStream GetOutputStream()
{
return mFileOutputStream;
}
//加载库和声明函数的
private native static FileDescriptor open(String path,int baudrates);
private native void close();
static {
System.loadLibrary("serialport");
}}//end of calss