Android Studio配置NDK并编译JNI文件so库 APP调用jni源码实例
一、Android studio 版本3.4.1

二、Android studio自带NDK

二、配置javah及ndk-build快速构建工具
1、配置ndk-build 用来编译jni,File-Settings-Tools-External Tools +
Program:C:\Android\Sdk\ndk-bundle\ndk-build.cmd (根据自己NDK的路径填写,如果是Ubuntu系统,去掉.cmd) Working directory:$ModuleFileDir$\src\main

2、配置javah 用来自动生成jni头文件,File-Settings-Tools-External Tools +
Program:$JDKPath$\bin\javah.exe(如果是Ubuntu系统,去掉.exe) Arguments:-classpath . -jni -d $ModuleFileDir$/src/main/jni $FileClass$ Working directory:$ModuleFileDir$\src\main\java

3、配置好后看到对应新增的menu

三、用javah工具生成jni头文件,并且生成so库。
1、新建nextouch.java文件
package com.example.nextouch; public class nextouch { public native int Read_register(int i2c_address,int register_address); public native int Write_register(int i2c_address,int register_address,int data); public native int Reset_chip(int period); }
2、鼠标右键选择javah编译会生成com_example_nextouch_nextouch.h

3、复制生成的.h 文件拷贝到同文件夹下,并把文件后缀改成.c,文件名字可以保持和 .h 文件同名,也可以如上图所示自定义文件名,.c文件内写入的就是各个JNI函数的具体C语言实现。我这里贴出我自己实际用到的com_example_nextouch_nextouch.c
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <stdint.h> #include <termios.h> #include <android/log.h> #include <sys/ioctl.h> #include "com_example_nextouch_nextouch.h" #include <jni.h> #include <android/log.h> /* Header for class com_example_nextouch_nextouch */ #define TAG "NEXTOUCH" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, TAG, __VA_ARGS__) #define CHIPS_DEV_NAME "/dev/nextouch_control" #define CHIPS_IOC_MAGIC 'k' #define CHIPS_IOC_SET_RESET_GPIO _IOW(CHIPS_IOC_MAGIC,8,unsigned char) int fd=-1; #ifdef __cplusplus extern "C" { #endif static int init_nextouch_i2c_device() { int ret; if((fd = open(CHIPS_DEV_NAME,O_RDWR|O_NDELAY))<0) { LOGI("open %s failed",CHIPS_DEV_NAME); ret=-1; } else { LOGI("open %s success!\n",CHIPS_DEV_NAME); ret=0; } return ret; } /** * chips_set_reset_gpio - 设置复位gpio电平?? @level: :非0为拉高,0为拉?? * @return: 成功返回0,失败返回负?? */ static int chips_set_reset_gpio(int level) { if(fd < 0) { fd = open(CHIPS_DEV_NAME,O_RDWR); if(fd == -1) { LOGE("<%s> Failed to open device for %s",__FUNCTION__,strerror(errno)); return -1; } } if(ioctl(fd,CHIPS_IOC_SET_RESET_GPIO,(unsigned long)&level) < 0) { LOGE("<%s> Failed to set reset_gpio state",__FUNCTION__); return -1; } return 0; } /* * Class: com_example_nextouch_nextouch * Method: Open * Signature: ()I */ JNIEXPORT jint JNICALL Java_com_example_nextouch_nextouch_Read_1register (JNIEnv *env, jobject obj,jint i2c_addr,jint address) { int ret; unsigned char buffer[3]; buffer[0] = (unsigned char)i2c_addr; buffer[1] = (unsigned char)address; buffer[2] = (unsigned char)0; if(fd <0) init_nextouch_i2c_device(); ret=read(fd,buffer,1); if(ret<0) { LOGI("i2c read failed! ret=%d errno=%d\n",ret,errno); return ret; } LOGI("Read_register i2c_addr=0x%02x address=0x%02x,data=0x%02x ret=%d",i2c_addr,address,buffer[0],ret); return buffer[0]; } /* * Class: com_example_nextouch_nextouch * Method: Close * Signature: ()I */ JNIEXPORT jint JNICALL Java_com_example_nextouch_nextouch_Write_1register (JNIEnv *env, jobject obj,jint i2c_addr,jint address, jint data) { int ret; unsigned char buffer[4]; buffer[0] = i2c_addr; buffer[1] = 0x02; buffer[2] = (unsigned char)address; buffer[3] = (unsigned char)data; if(fd <0) init_nextouch_i2c_device(); ret = write(fd,buffer,4); if(ret<0) { LOGI("i2c write failed! ret=%d errno=%d\n",ret,errno); return ret; } LOGI("Write_register i2c_addr=0x%02x,address=0x%02x,data=0x%02x buffer[0]=0x%02x ret=%d",i2c_addr,address,data,buffer[0],ret); return buffer[0]; } /* * Class: com_example_nextouch_nextouch * Method: Ioctl * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_example_nextouch_nextouch_Reset_1chip (JNIEnv *env, jobject obj, jint period) { int ret; unsigned char buffer[4]; buffer[0] = 0; buffer[1] = 0x03; buffer[2] = (unsigned char)0; buffer[3] = (unsigned char)period; if(fd <0) init_nextouch_i2c_device(); ret = write(fd,buffer,4); if(ret<0) { LOGI("Reset failed!\n"); return ret; } //chips_set_reset_gpio(0); LOGI("Reset_chip address=0x%02x,data=0x%02x buffer[0]=0x%02x",0,period,buffer[0]); return buffer[0]; } #ifdef __cplusplus } #endif
4、添加Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nextouch LOCAL_SRC_FILES := com_example_nextouch_nextouch.c LOCAL_LDLIBS += -llog LOCAL_LDLIBS +=-lm include $(BUILD_SHARED_LIBRARY)
5、添加Application.mk
APP_ABI := armeabi-v7a arm64-v8a
6、ndk-build编译,会在libs下生成两个文件夹

7、自动在jni的同级目录生成一个libs目录,到这里已经编译出so库,接下来是如果在app里面调用这些jni接口了。

四、app调用jni接口
1、再需要调用jni接口的java文件里面添加
static { System.loadLibrary("nextouch"); }

2、调用接口

3、app/build.gradle文件里面添加
sourceSets { main { jni.srcDirs = [] //jniLibs.srcDirs = ['libs']// include .so file into apk jniLibs.srcDirs = ['src/main/libs']// include .so file into apk // reference: http://stackoverflow.com/questions/24357687/how-to-include-so-library-in-android-studio-really } }

4、可以编译了生apk了

5、真机测试ok

五,源码路径:https://download.csdn.net/download/qq_37858386/12833466