Android studio配置javah及ndk-build快速构建工具

Android Studio配置NDK并编译JNI文件so库 APP调用jni源码实例

一、Android studio 版本3.4.1

3 20200910172358348

二、Android studio自带NDK

3 20200910172655519

二、配置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
3 20200910183137961

  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 20200910173834156

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

3 20200910174113764

三、用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 2020091017481319

  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下生成两个文件夹

3 20200910175554592

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

10

四、app调用jni接口

   1、再需要调用jni接口的java文件里面添加

static {
	System.loadLibrary("nextouch");
}
3 20200910180100252

2、调用接口

3 20200910180253402

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
	}
}
3 20200910180607964

  4、可以编译了生apk了

3 20200910180915891

   5、真机测试ok

3 2020091018152345

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

转载自该处

0