Android JNI基础
JNI/NDK的区别
JNI和NDK都是调用C/C++代码库。所以总体来说,除了应用场景不一样,其他没有太大区别。细微的区别就是:JNI可以在Java和Android中同时使用,NDK只能在Android里面使用。
其主要作用就是快捷调用C/C++的动态链接库。
NDK的配置方法
settings里面

然后在settings下面有一个project structure,里面配置ndk目录

NDK的使用
打开一个新的项目,选择以C++方式启动,然后一路next即可

正式学习JNI开发
可以看到MainAvtivity较之以往多了这样两段代码

我们知道static关键字的作用就是首先执行代码块内的代码,这里就是先加载“native-lib”这样一个文件。
在c文件夹中也出现了native-lib这样一个文件,里面有着一段看着很奇怪的代码
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_four1er_demoNative_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
上面提到的 public native String stringFromJNI() 方法的实现就是在这里,那怎么知道 Java 中的某个 native 方法是对应的 cpp 中的哪个方法呢?这就和 JNI 的注册有关了,本例中使用的是静态注册,即 “Java包名类名_方法名” 的形式,其中包名也是用下划线替代点号。
整个调用流程就是:
- Gradle 调用您的外部构建脚本 CMakeLists.txt。
- CMake 按照构建脚本中的命令将 C++ 源文件 native-lib.cpp 编译到共享的对象库中,并命名为 libnative-lib.so,Gradle 随后会将其打包到 APK 中。
- 运行时,应用的 MainActivity 会使用 System.loadLibrary() 加载原生库。现在,应用可以使用库的原生函数 stringFromJNI()。
- MainActivity.onCreate() 调用 stringFromJNI(),这将返回“Hello from C++”并使用这些文字更新 TextView。
让我们一点点看这段代码
首先是JNIEXPORT
跟进去:

#define JNIEXPORT __attribute__ ((visibility ("default")))
意思大致是默认的意思,
还有JNICALL
#define JNICALL
定义了个寂寞
这两个就忽视掉。
然后看jstring,这里引入jni,java,c的数据类型对应关系

跟进去也可以看到jstring是属于object类型的,毕竟java中String类型本来就是引用类型,是可以new出的
至于Java_com_four1er_demoNative_MainActivity_stringFromJNI,这个只能说看着吓唬人,分解下就是Java下com.four1er.demoNative(包名)mainActivity(类名)stringFromJNI(方法名)
补充:
JNIEnv* 代表了Java环境,几乎封装了所有的jni方法,通过这个JNIEnv* 指针,就可以对Java端的代码进行操作。JNIEnv 只在创建它的线程生效,不能跨线程传递,不同线程的 JNIEnv 彼此独立。
我们 JNI 的绝大多数操作都是通过这两者来调用到 JNINativeInterface 和 JNIInvokeInterface 结构体里的相关方法。


其中 JavaVM 是一个全局变量,一个进程只有一个 JavaVM 对象。
而 JNIEnv 是一个线程拥有一个,不同线程的 JNIEnv 彼此独立。
jobject 代表这个native方法的类实例或这个类的class对象。
JNI方法大全及使用示例:
JNI 有 C、C++ 两种代码风格,即:
C风格:(*env)->NewStringUTF(env, "Hellow World!");
C++风格:env->NewStringUTF("Hellow World!");
这里函数太多,主要展示一下在native.cpp中出现的NewStringUTF()函数
jstring NewStringUTF(const char* bytes)
说明:以 UTF-8 的编码方式创建一个 Java 的字符串
参数:
bytes:指向字符数组的指针
就是很简单的先创建一个字符数组: std::string hello = "Hello from C++";
然后传入NewStringUTF(hello.c_str())然后返回一个jstring类型对象,也就是java类型的String类型对象。
然后在onCreate方法中
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
即可展示出字符。
大量的实例参照https://blog.csdn.net/afei__/article/details/81016413,强烈推荐~

浙公网安备 33010602011771号