1、定义包含native方法的java类

package android.serialport.api;import android.util.Log;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;/** * Create by Jason.Yin 2018/4/24. */public class SerialPort {    private static final String TAG = "SerialPort";    /*     Do not remove or rename the field mFd: it is used by native method close();     */    private FileDescriptor mFd;    private FileInputStream mFileInputStream;    private FileOutputStream mFileOutputStream;    public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {        /* Check access permission, the serial port must can be write and read */        if (!device.canRead() || !device.canWrite()) {            try {                Process su;                su = Runtime.getRuntime().exec("/system/bin/su");                String cmd = "chmod 666 " + device.getAbsolutePath() + "\n" + "exit\n";                su.getOutputStream().write(cmd.getBytes());                if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {                    throw new SecurityException();                }            } catch (Exception e) {                e.printStackTrace();                throw new SecurityException();            }        }        mFd = open(device.getAbsolutePath(), baudrate, flags);        if (mFd == null) {            Log.e(TAG, "native open returns null");            throw new IOException();        }        mFileInputStream = new FileInputStream(mFd);        mFileOutputStream = new FileOutputStream(mFd);    }    public InputStream getInputStream() {        return mFileInputStream;    }    public OutputStream getOutputStream() {        return mFileOutputStream;    }    //Definition jni method    private native static FileDescriptor open(String path, int baudrate, int flags);    public native void close();    static {        System.loadLibrary("serial_port");    }}

2、利用《[Android jni开发系列(二)]AndroidStudio移植eclipse NDK项目开发》中定义的javah命令生成jni的头文件

android_serialport_api_SerialPort.h/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class android_serialport_api_SerialPort */#ifndef _Included_android_serialport_api_SerialPort#define _Included_android_serialport_api_SerialPort#ifdef __cplusplusextern "C" {#endif/* * Class:     android_serialport_api_SerialPort * Method:    open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */JNIEXPORT jobject JNICALL Java_android_serialport_api_SerialPort_open  (JNIEnv *, jclass, jstring, jint, jint);/* * Class:     android_serialport_api_SerialPort * Method:    close * Signature: ()V */JNIEXPORT void JNICALL Java_android_serialport_api_SerialPort_close  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

3、实现android_serialport_api_SerialPort.h中的方法

//// Created by Jason.Yin on 2018/4/11.///* DO NOT EDIT THIS FILE - it is machine generated */#include #include #include #include #include #include #include #include"android_serialport_api_SerialPort.h"#include 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 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_api_SerialPort * Method:    open * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor; */JNIEXPORT jobject JNICALL Java_android_serialport_api_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) {        /* TODO: throw an exception */        LOGE("Invalid baudrate");        return NULL;    }    /* Opening device */    {        jboolean iscopy;        const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);        LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);        fd = open(path_utf, O_RDWR | flags);        LOGD("open() fd = %d", fd);        (*env)->ReleaseStringUTFChars(env, path, path_utf);        if (fd == -1) {            /* Throw an exception */            LOGE("Cannot open port");            /* 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 */            return NULL;        }        cfmakeraw(&cfg);        cfsetispeed(&cfg, speed);        cfsetospeed(&cfg, speed);        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, "", "()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:     android_serialport_api_SerialPort * Method:    close * Signature: ()V */JNIEXPORT void JNICALL Java_android_serialport_api_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);    close(descriptor);}

4、配置gradle.properties和build.gradle文件

gradle.propertiesandroid.useDeprecatedNdk=true //添加这行
build.gradle    defaultConfig {       ...        ndk {            moduleName "serial_port"            ldLibs "log", "z", "m"  //log依赖//           abiFilters "armeabi", "armeabi-v7a", "x86"  //ndk 版本不能用最新的,本人测试android-ndk-r15c可以,其它的没试//            abiFilters "armeabi-v7a", "x86" //ndk版本17.0.4640043 rc1不支持armeabi,否则编译会出错        }    }

5、编译工程后会在下图所示目录生成对应so库
[Android jni开发系列(四)]利用jni开发生成Android串口开发的so库_第1张图片

更多相关文章

  1. Android统一依赖多个不同版本的Support v7包
  2. [置顶] 找到一个在Android上创建阻塞式模态对话框的方法
  3. Android来电拦截的实现方法
  4. Android Studio集成Library时报错,终极解决方法
  5. 【Android UI】自定义圆形Loading动画
  6. Android从服务器获取图片的实例方法
  7. android屏幕休眠和唤醒两种方法(newWakeLock)
  8. 自定义ListView4

随机推荐

  1. 分析B站100万+视频,发现竟然有这么多干货
  2. 如何做出好看的可视化视频?这是我最舍不得
  3. 使用Flask在服务器实现一个API接口。
  4. 是今天网不好吗?
  5. Python 中更优雅的环境变量设置方案
  6. 就想写个爬虫,我到底要学多少东西啊?
  7. 史上规模最大的中文知识图谱以及估值两个
  8. 用Python获取公众号阅读数、点赞数。
  9. 数据探索很麻烦?推荐一款史上最强大的特征
  10. 给Python初学者的最好练手项目,进来看就对