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,强烈推荐~

posted @ 2021-01-11 17:44  four1er  阅读(186)  评论(0)    收藏  举报