一 JNI原理
1 编译
cpu识别的是“0101”的字符
c/c++ ========= 二进制文件
-
编译:xxx.c ------> windows .obj 语法 Linux .o
-
链接:.o -----> log.so
2 编译规则:
- Eclipse GUN ----> Android.mk
- Android Studio: LLVM ----> CMakeList.txt
三段式
cppFlags “-frtti -fexceptions”
3 Jni原理
二 AS新建一个支持JNI的项目
1 新建项目
new Project 勾选下面两项即可,在CMakeList.txt中配置对应的c文件声明
CMakeList.txt 用来进行JNI引用的配置
add_library 指定需要编译那些文件
target_link_libraries 指定了需要链接那些so库
JNI项目一定包含指定编译文件和需要链接哪些so库这两个动作
注意: 新建项目报错:External Native Build Issues
解决方法:提升.build:gradle版本
由
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
}
提升至:
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
2 初始化
- 将cpp路径下的native-lib.cpp删除,清理MainActivity的jni调用,并新建一个native-lib.c文件,
- 切换到Project视图,在src/main/cpp下面可以找到native-lib.c
- 在CMakeList.txt中修改配置:add_library 中原先配置的native-lib.cpp修改为新建的ative-lib.c文件路径:src/main/cpp/native-lib.c
3 声明一个native 方法,生成.h头文件
- 创建一个java类,其中声明一个native方法
public class FileUtils {
public static native void diff(String path,String pattern_Path,int file_number );
}
- 可以直接快捷键生产头文件,或者javah直接生成
- 如果javah失败,可以:
先生成class文件
C:\rj\workspace\NDK\app\src\main\java\com\ray\ndk\ndk>javac FileUtils.java
然后javah,注意两条命令的路径
C:\rj\workspace\NDK\app\src\main\java>javah -classpath . -jni com.ray.ndk.ndk.FileUtils
最好在\java路径下生成一个com_ray_ndk_ndk_FileUtils.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_ray_ndk_ndk_FileUtils */
#ifndef _Included_com_ray_ndk_ndk_FileUtils
#define _Included_com_ray_ndk_ndk_FileUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_ray_ndk_ndk_FileUtils
* Method: diff
* Signature: (Ljava/lang/String;Ljava/lang/String;I)V
*/
JNIEXPORT void JNICALL Java_com_ray_ndk_ndk_FileUtils_diff
(JNIEnv *, jclass, jstring, jstring, jint);
#ifdef __cplusplus
}
#endif
#endif
4 实现.h定义的方法
- 将要实现的方法拷贝到native-lib.c中,c中引入com_ray_ndk_ndk_FileUtils.h
- 引入#include <android/log.h>打印日志
- 定义
#define TAG “RAY”
#define LOGI(…) __android_log_print(ANDROID_LOG_INFO, TAG, VA_ARGS) - 实现
#include "com_ray_ndk_ndk_FileUtils.h"
#include <android/log.h>
#define TAG "RAY"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
JNIEXPORT void JNICALL Java_com_ray_ndk_ndk_FileUtils_diff
(JNIEnv * env, jclass clazz, jstring path, jstring pattern_Path, jint file_num){
LOGI("JNI的方法被调用");
}
5 使用
- 加载库
public class FileUtils {
static {
System.loadLibrary("native-lib");
}
public static native void diff(String path,String pattern_Path,int file_number );
}
- 调用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
diff();
}
public void diff(){
Log.d("RAY", "diff");
FileUtils.diff("ss","33" ,4 );
}
}
- 运行后打印:
03-21 10:39:20.212 24471-24471/com.ray.ndk.ndk D/Ray: diff
03-21 10:39:20.213 24471-24471/com.ray.ndk.ndk I/RAY: JNI的方法被调用