JNI 转载&安利&补充

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cjh_android/article/details/79425568

推荐

标题大大的推荐,显示了我对将要安利的文章的推崇:Android:JNI 与 NDK到底是什么?(含实例教学)。这篇文章非常详细的记录了 AS 的 2.2 版本之前 JNI 的开发步骤。在这基础上我会做一些修修补补的工作。

修补一 : ndk 环境配置

在安利的博文中其实已经有了MAC相关的环境配置操作,可以看成 Linux 也是如此。我要补充的是 Win10 的环境配置,直接上图:

下载

这里写图片描述

环境配置
我的 ndk 路径:E:\android\sdk\ndk-bundle
第一步: NDK_ROOT

这里写图片描述

第二步:PATH 中填写 %NDK_ROOT%

这里写图片描述

修补二 : ndk-build 不是内部或外部命令,也不是可运行的程序

在配置完以上的环境变量之后,我在 AS 的 Terminal 窗口切换到 jni 目录之后,却依然出现了以上的错误:

这里写图片描述

究竟为什么我也懒得管,毕竟我只是偶尔使用 windows 而已,大部分时候,都是跑着 Linux 开发,给个解决方案: ndk-build -C Project_JNI_PATH

这里写图片描述

如上图所示,我先切换到 ndk 的下载路径,然后直接调用 ndk-build -C 命令,输入想要编译的 JNI 文件夹,然后成功编译。最后给一个 ndk-build 的命令博客链接,记不得了直接看一下:NDK开发之ndk-build命令详解

修补三 : 基于 AS 的2.2 版本 Your project contains C++ files but it is not using a supported native build system.

错误:这里写图片描述

贴出我的 build.gradle & gradle.properties

这里写图片描述

这里写图片描述


至此一些环境,编译的部分的修补到此为止。接下来,就是对于 JNI 部分技术的补充。

JNI 技术补充

补充一:JNI C/C++ 调用 Java

在大部分 JNI 的文章中大多只介绍了 Java 如何调用 Native 的过程,却没有介绍到 Native 是如何调用 Java 的,以下我写了一个简单的调用以供参考。
这里写图片描述
如上图,changeTextColorByJNI() 这个方法的功能就像方法名所描述的那样,通过 Native 层来调用 MainActivit 中的函数:
这里写图片描述
接下来,来看下 test.cpp 里面的代码吧:
这里写图片描述
就像开篇介绍的文章里面所说的那样 JNIEXPORT & JNICALL 这两个关键字是不能少的,你可以理解为这是一种标记。如上图所看到的其实到这里,也就结束了。最终,这个方法会调用到 MainActivity 中的 changeTextColor 方法,将字体变成红色。
那么接下来,就是详细的讲解了。
从 getFromJNI 和 changeTextColorByJNI 方法中其实都可以看出来,他们的方法参数里面都多了这样两个参数: JNIEnv 和 jobject。那么这两个参数到底代表了什么意思呢。

JNIEnv:

JNIEnv 是一个与线程相关的代表JNI环境的结构体。用一种不够全面的通俗的话来讲,JNIEnv 是就是为我们能处理 Java 而存在的,它可以调用 Java 函数,可以操作 jobject 对象的很多事情。对于我个人来说,我甚至是把它看成是 JVM 在JNI 环境中的代表似的存在,虽然这样绝对不全面。这样看的理由:JNIEnv 是 通过调用 JVM 的 AttachCurrentThread 函数所得到的。

jobject:

通过介绍的文章我们可以知道 除了基本数据类型、Class 和 string,其他 Java 层的对象在 JNI 中都是用 jobject 所代表的,那么这里的 jobject 其实代表的就是 MainActivity 这个对象。它的意思就是,我们实在 MainActivity 的哪一个对象上调用 changeTextColor 方法的。

调用Java 方法第一步: 通过 JNIEnv 获得 MainActivity 在 JNI 层所对应的 jclass 实例
jclass mainActivityInterface = env -> FindClass("study/jni/com/staticregister/MainActivity");
调用Java 方法第二步: 取出 MainActivity 类中函数 changeTextColor 的 jmethodID
jmethodID mChangeTextColorByJNI = env -> GetMethodID(mainActivityInterface, "changeTextColor", "()V");
调用Java 方法第三步: 调用 JNIEnv 的 CallVoidMethod 函数
env->CallVoidMethod(obj, mChangeTextColorByJNI);

至此 Native 调用 Java 的简单实例就完成了。其实在 JNIEnv 中还提供了大量的其他的方法例如:

获取字段的方法:
jfieldID GetFieldID(jclass clazz, const char *name, const char *sig)
NativeType Get<type>Field(JNIEvn *evn, jobject obj, jfieldID fieldID)
....

调用不同方法的:
NativeType Call<type>Method(JNIEvn *env, jobject obj, jmethodID methodID, params...)

猜你喜欢

转载自blog.csdn.net/cjh_android/article/details/79425568
JNI