android 串口jni 开发流程

来源:互联网 发布:sql中不等于怎么表示 编辑:程序博客网 时间:2024/05/28 15:26


        第一步, 在eclipose里新建一个android工程,再新建一个 SerialPort.java文件

package android.serialport;public class SerialPort {//本类方法,这里略过,主要是调用jni方法以给其他类提供方法。    ......// JNI  方法    private native static FileDescriptor open(String path, int baudrate) throws IOException;    private native void native_close();    private native int native_read_array(byte[] buffer, int length) throws IOException;    private native int native_read_direct(ByteBuffer buffer, int length) throws IOException;    private native int native_read_array_timeval(byte[] buffer, int length, int tv_sec, int tv_usec) throws IOException;    private native int native_read_direct_timeval(ByteBuffer buffer, int length, int tv_sec, int tv_usec) throws IOException;    private native void native_write_array(byte[] buffer, int length) throws IOException;    private native void native_write_direct(ByteBuffer buffer, int length) throws IOException;static {System.loadLibrary("serial_port");}}

        第二步,生成共享库头文件。进入eclipose刚才所新建工程的/bin/classes/目录下。可以看到其目录下的android/serialport/SerialPort.class文件,这个文件就是eclipose自动编译生成的classes文件。

        执行: javah android.serialport.SerialPort  (注意把目录符“/”换成“.”,而且没有.classes)

就会在当前目录下生成android_serialport_SerialPort.h 头文件,查看android_serialport_SerialPort.h有时会多余些错误处,如Java_android_serialport_SerialPort_native_1open函数名,明显多了一个“1”,此处不懂为什么多了个“1”。但千万不要去掉它.

       第三步,将刚才生成的H文件拷贝到jni源文件目录。因为我们这里是用ubuntu下ndk编译的。所以将android_serialport_SerialPort.h改名成SerialPort.h后,实现SerialPort.c文件,SerialPort.c就是要实现刚才SerialPort.h里面的所有方法。

SerialPort.h : 用javah 命令产生的

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class android_serialport_SerialPort */#ifndef _Included_android_serialport_SerialPort#define _Included_android_serialport_SerialPort#ifdef __cplusplusextern "C" {#endif/* * Class:     android_serialport_SerialPort * Method:    native_open * Signature: (Ljava/lang/String;I)Ljava/io/FileDescriptor; */JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_native_1open  (JNIEnv *, jclass, jstring, jint);/* * Class:     android_serialport_SerialPort * Method:    native_close * Signature: ()V */JNIEXPORT void JNICALL Java_android_serialport_SerialPort_native_1close  (JNIEnv *, jobject);/* * Class:     android_serialport_SerialPort * Method:    native_read_array * Signature: ([BI)I */JNIEXPORT jint JNICALL Java_android_serialport_SerialPort_native_1read_1array  (JNIEnv *, jobject, jbyteArray, jint);/* * Class:     android_serialport_SerialPort * Method:    native_read_direct * Signature: (Ljava/nio/ByteBuffer;I)I */JNIEXPORT jint JNICALL Java_android_serialport_SerialPort_native_1read_1direct  (JNIEnv *, jobject, jobject, jint);.........#ifdef __cplusplus}#endif#endif
SerialPort.c : 实现SerialPort.h中声明的函数

#include "termios.h"#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <jni.h>#include "SerialPort.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)//static jfieldID field_context;   // cannot define this , use this will anr.  why??????/* * Class:     android_serialport_SerialPort * Method:    native_open * Signature: (Ljava/lang/String;I)Ljava/io/FileDescriptor; */JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_native_1open  (JNIEnv *env, jclass thiz, jstring path, jint baudrate){        int fd;        speed_t speed;        jobject mFileDescriptor;        /* Check arguments */        {                speed = getBaudrate(baudrate);                if (speed == -1) {                        /* TODO: throw an exception */                        LOGE("Invalid baudrate");                        jniThrowException(env, "java/io/IOException bad baudrate!!!!!", NULL);                        return NULL;                }        }        /* Opening device */        {                jboolean iscopy;                const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);                LOGD("Opening serial port %s", path_utf);                fd = open(path_utf, O_RDWR);                LOGD("open() fd = %d", fd);        //      (*env)->SetIntField(env,thiz, field_context, fd);  // cannot define this , use this will anr.  why??????                (*env)->ReleaseStringUTFChars(env, path, path_utf);                if (fd == -1)                {                        /* Throw an exception */                        LOGE("Cannot open port");                        jniThrowException(env, "java/io/IOException", NULL);                                  /* TODO: throw an exception */                        return NULL;                }        }        /* Configure device */        {                struct termios cfg;                LOGD("Configuring serial port");                if (tcgetattr(fd, &cfg))                {                        LOGE("tcgetattr() failed");                        close(fd);                        /* TODO: throw an exception */                        jniThrowException(env, "java/io/IOException", NULL);                        return NULL;                }                cfmakeraw(&cfg);                cfsetispeed(&cfg, speed);                cfsetospeed(&cfg, speed);                if (tcsetattr(fd, TCSANOW, &cfg))                {                        LOGE("tcsetattr() failed");                        close(fd);                        /* TODO: throw an exception */                        jniThrowException(env, "java/io/IOException", NULL);                        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);        }               return mFileDescriptor;}/* * Class:     cedric_serial_SerialPort * Method:    close * Signature: ()V */JNIEXPORT void JNICALL Java_android_serialport_SerialPort_native_1close  (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);        close(descriptor);}..........

第四步,编写Android.mk

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)TARGET_PLATFORM := android-3LOCAL_MODULE    := serial_portLOCAL_SRC_FILES := SerialPort/SerialPort.c JNIHelp.cppLOCAL_LDLIBS    := -lloginclude $(BUILD_SHARED_LIBRARY)

第五步,编译,执行ndk-build命令,将会产生serial_port.so文件

第六步,将serial_port.so文件拷贝到eclipse项目 project/libs/armeabi/下,至此OK。





0 0
原创粉丝点击