===步骤:=========================================
1.eclipse下搭建ndk(android-ndk-r10c)环境;
2.定义本地调用接口(动态库导出函数);
3.javah生成头文件;
4.实现c/cpp;
5.编译;
6.加载System.loadLibrary("");
================================================
1.eclipse下搭建ndk(android-ndk-r10c)环境:
ndk:交叉编译环境,内含虚拟机;
2.定义本地调用接口(动态库导出函数):
package com.rdaonicelk.dev.com.comaccess;
public class SerialPortNative
{
...
static private native int open(String path, int bandrate);
static private native void close(int fd);
static private native int write(int fd, byte[] data);
static private native int write(int fd, byte[] data, int off, int len);
static private native int read(int fd, byte[] data);
static private native int read(int fd, byte[] data, int off, int readLen);
static private native int getErrno();
static
{
System.loadLibrary("SerialPortNative");
}
}
3.javah生成头文件:
(对SerialPortNative.class文件生成头文件)
javah com.rdaonicelk.dev.com.comaccess.SerialPortNative
4.实现c/cpp:
注意:"*.c"和"*.cpp"对应的JNIEnv宏的定义不一样,以下是"*.c"的使用方法
#include "com_rdaonicelk_dev_com_comaccess_SerialPortNative.h"
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/*
* Class: com_rdaonicelk_dev_com_comaccess_SerialPortNative
* Method: open
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_open
(JNIEnv *env, jclass thiz, jstring path, jint baud)
{
int fd; /* File descriptor for the port */
int nRet;
speed_t speed;
/* Check arguments */
speed = getBaudrate(baud);
if (speed == -1)
{
return -1;
}
jboolean iscopy;
const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
fd = open(path_utf, O_RDWR | O_NOCTTY | O_NDELAY);
(*env)->ReleaseStringUTFChars(env, path, path_utf);
if (fd == -1)
{
return -2;
}
fcntl(fd, F_SETFL, 1);//async
//fcntl(fd, F_SETFL, 0);//sync
/* Configure device */
struct termios cfg;
if (tcgetattr(fd, &cfg) != 0)
{
//LOGE("tcgetattr() failed");
close(fd);
return -3;
}
cfmakeraw(&cfg);
cfsetispeed(&cfg, speed);
cfsetospeed(&cfg, speed);
/*
* Enable the receiver and set local mode...
*/
cfg.c_cflag |= (CLOCAL | CREAD);
cfg.c_cflag &= ~PARENB;
cfg.c_cflag &= ~CSTOPB;
cfg.c_cflag &= ~CSIZE;
cfg.c_cflag |= CS8;
nRet=ioctl(fd, TCSETS, &cfg);
// if (tcsetattr(fd, TCSANOW, &cfg) != 0)
// {
// close(fd);
// return -4;
// }
return fd;
}
JNIEXPORT void JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_close
(JNIEnv *env, jclass thiz, jint fd)
{
if(fd < 0)
{
return;
}
close(fd);
return;
}
/*
* Class: com_rdaonicelk_dev_com_comaccess_SerialPortNative
* Method: write
* Signature: (I[B)I
*/
JNIEXPORT jint JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_write__I_3B
(JNIEnv *env, jclass thiz, jint fd, jbyteArray data)
{
int dataSize=(*env)->GetArrayLength(env, data);
unsigned char * p=(*env)->GetByteArrayElements(env, data, JNI_FALSE);
int nRet=write(fd, p, dataSize);
(*env)->ReleaseByteArrayElements(env,data,p,0);
return nRet;
}
/*
* Class: com_rdaonicelk_dev_com_comaccess_SerialPortNative
* Method: write
* Signature: (I[BII)I
*/
JNIEXPORT jint JNICALL Java_com_rdaonicelk_dev_com_comaccess_SerialPortNative_write__I_3BII
(JNIEnv *env, jclass thiz, jint fd, jbyteArray data, jint off, jint len)
{
int dataSize=(*env)->GetArrayLength(env, data);
unsigned char * p=(*env)->GetByteArrayElements(env, data, JNI_FALSE);
int nRet=write(fd, p+off, len);
(*env)->ReleaseByteArrayElements(env,data,p,0);
return nRet;
}
5.编译:
创建Android.mk.声明需ndk编译的源文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := SerialPortNative
LOCAL_SRC_FILES := com_<span style="font-family: Arial, Helvetica, sans-serif;">rdaonicelk</span><span style="font-family: Arial, Helvetica, sans-serif;">_dev_com_comaccess_SerialPortNative.c</span>
include $(BUILD_SHARED_LIBRARY)
创建Application.mk,指定交叉编译的目标CPU架构
可指定编译输出多个不同CPU架构目标文件,用空格分隔.或使用关键字"all"指定生成所有支持的CPU架构的目标文件
APP_ABI := armeabi
6.加载System.loadLibrary(""):
static
{
System.loadLibrary("SerialPortNative");
}