java基础教程98

java基础教程98Android 的 NDK 开发 1 Android JNI 简介与调用流程 1 JNI 简介 JNI 全称为 Java Native Interface JAVA 本地调用 从 Java1 1 开始 JNI 成为 java 平台的一部分 它允许 Java 代码和其他语言写的代码 如 C amp C 进行交互 并非从 Android 发布才引入 JNI 的概念的 2 JNI 与 NDK 简单来说

大家好,我是讯享网,很高兴认识大家。



Android的NDK开发(1)————Android JNI简介与调用流程

1、JNI简介

JNI全称为Java Native Interface(JAVA本地调用)。从Java1.1开始,JNI成为java平台的一部分,它允许Java代码和其他语言写的代码(如C&C++)进行交互。并非从Android发布才引入JNI的概念的。

2、JNI与NDK

简单来说,Android的NDK提供了一些交叉编译工具链和Android自带的库,这些Android的库可以让开发者在编写本地语言的程序时调用。而NDK提供的交叉编译工具链就对已经编写好的C&C++代码进行编译,生成库。

当然了,你也可以自己搭建交叉编译环境,而不用NDK的工具和库。然后生成库,只要规范操作,一样可以生成能让JAVA层成功调用的库文件的。

利用NDK进行编译本地语言可以参考这篇博文:

/conowen/article/details/

3、JNI 调用流程

众所周知,Android的应用层的类都是以Java写的,这些Java类编译为Dex文件之后,必须靠Dalvik 虚拟机( Virtual Machine)来执行。假如在执行java程序时,需要载入C&C++函数时,Dalvik虚拟机就会去加载C&C++的库,(System.loadLibrary("libName");)让java层能顺利地调用这些本地函数。需要清楚一点,这些C&C++的函数并不是在Dalvik虚拟机中运行的,所以效率和速度要比在Dalvik虚拟机中运行得快很多。

Dalvik虚拟机成功加载库之后,就会自动地寻找库里面的JNI_OnLoad函数,这个函数用途如下:(1)告诉Dalvik虚拟机此C库使用哪一个JNI版本。如果你的库里面没有写明JNI_OnLoad()函数,VM会默认该库使用最老的JNI 1.1版本。但是新版的JNI做了很多的扩充,也优化了一些内容,如果需要使用

JNI的新版功能,就必须在JNI_OnLoad()函数声明JNI的版本。如

[java]view plaincopy

1.result = JNI_VERSION_1_4;

当没有JNI_OnLoad()函数时,Android调试信息会做出如下提示(No JNI_OnLoad found)

[java]view plaincopy

1.04-2913:53:1

2.184: D/dalvikvm(361): Trying to load lib /data/data/com.conowen.helloworld/l

ib/libHelloWorld.so 0x44edea98

2.04-2913:53:12.204: D/dalvikvm(361): Added shared lib /data/data/com.conowen.helloworld/lib

/libHelloWorld.so 0x44edea98

3.04-2913:53:12.204: D/dalvikvm(361): No JNI_OnLoad found in /data/data/com.conowen.hellowor

ld/lib/libHelloWorld.so 0x44edea98, skipping init

(2)因为Dalvik虚拟机加载C库时,第一件事是调用JNI_OnLoad()函数,所以我们可以在JNI_OnLoad()里面进行一些初始化工作,如注册JNI函数等等。注册本地函数,可以加快java层调用本地函数的效率。另外:与JNI_OnLoad()函数相对应的有JNI_OnUnload()函数,当虚拟机释放该C库时,则会调用JNI_OnUnload()函数来进行善后清除动作。

4、例子(关于jni里面的数据类型转换与常用jni方法下一篇博文介绍)

下面以havlenapetr的FFmpeg工程里面的onLoad.cpp为例详细说一下:

[cpp]view plaincopy

1https://www.360docs.net/doc//onLoad.cpp文件

2.

3.#define TAG "ffmpeg_onLoad"

4.

5.#include

6.#include

7.#include "jniUtils.h"

8.

9.extern"C" {

10.

11.extern int register_android_media_FFMpegAVRational(JNIEnv *env);

12.

13.#ifdef BUILD_WITH_CONVERTOR

14.extern int register_android_media_FFMpeg(JNIEnv *env);

15.#endif

16.

17.extern int register_android_media_FFMpegAVFormatContext(JNIEnv *env);

18.extern int register_android_media_FFMpegAVInputFormat(JNIEnv *env);

19.

21.

22.extern int register_android_media_FFMpegAVCodecContext(JNIEnv *env);

23.extern int register_android_media_FFMpegUtils(JNIEnv *env);

24.extern int register_android_media_FFMpegAVFrame(JNIEnv *env);

25.

26.#ifdef BUILD_WITH_PLAYER

27.extern int register_android_media_FFMpegPlayerAndroid(JNIEnv *env);

28.#endif

29.

30.static JavaVM *sVm;

31.

32https://www.360docs.net/doc/*

33. * Throw an exception with the specified class and an optional message.

34. */

35.int jniThrowException(JNIEnv* env, const char* className, const char* msg) {

36. jclass exceptionClass = env->FindClass(className);

37.if (exceptionClass == NULL) {

38. __android_log_print(ANDROID_LOG_ERROR,

39. TAG,

40."Unable to find exception class %s",

41. className);

42.return -1;

43. }

44.

45.if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {

46. __android_log_print(ANDROID_LOG_ERROR,

47. TAG,

48."Failed throwing '%s' '%s'",

49. className, msg);

50. }

51.return 0;

52.}

53.

54.JNIEnv* getJNIEnv() {

55. JNIEnv* env = NULL;

56.if (sVm->GetEnv((void) &env, JNI_VERSION_1_4) != JNI_OK) {

57. __android_log_print(ANDROID_LOG_ERROR,

58. TAG,

59."Failed to java基础教程98 obtain JNIEnv");

60.return NULL;

61. }

62.return env;

小讯
上一篇 2024-12-26 11:09
下一篇 2024-12-25 19:54

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/10326.html