拓胜技术专家教你如何深入理解AndroidNative

上传人:cl****1 文档编号:506661702 上传时间:2023-10-26 格式:DOC 页数:15 大小:102.50KB
返回 下载 相关 举报
拓胜技术专家教你如何深入理解AndroidNative_第1页
第1页 / 共15页
拓胜技术专家教你如何深入理解AndroidNative_第2页
第2页 / 共15页
拓胜技术专家教你如何深入理解AndroidNative_第3页
第3页 / 共15页
拓胜技术专家教你如何深入理解AndroidNative_第4页
第4页 / 共15页
拓胜技术专家教你如何深入理解AndroidNative_第5页
第5页 / 共15页
点击查看更多>>
资源描述

《拓胜技术专家教你如何深入理解AndroidNative》由会员分享,可在线阅读,更多相关《拓胜技术专家教你如何深入理解AndroidNative(15页珍藏版)》请在金锄头文库上搜索。

1、Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C、C+ 和汇编语言)编写的应用程序和库进行交互操作。1.从如何载入.so档案谈起由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Bytecode之后,必须靠Dalvik虚拟机(VM: Virtual Machine)来执行。VM在Android平台里,扮演很重要的角色。此外,在执行Java类的过程中,如果Java类需要与

2、C组件沟通时,VM就会去载入C组件,然后让Java的函数顺利地调用到C组件的函数。此时,VM扮演着桥梁的角色,让Java与C组件能通过标准的JNI介面而相互沟通。应用层的Java类是在虚拟机(VM: Vitual Machine)上执行的,而C件不是在VM上执行,那么Java程式又如何要求VM去载入(Load)所指定的C组件呢? 可使用下述指令:System.loadLibrary(*.so的档案名);例如,Android框架里所提供的MediaPlayer.java类,含指令:Java代码:1. public class MediaPlayer2. static 3. System.load

3、Library(media_jni);4. 5.6. 7.8.复制代码这要求VM去载入Android的/system/lib/libmedia_jni.so档案。载入*.so之后,Java类与*.so档案就汇合起来,一起执行了。2.如何撰写*.so的入口函数JNI_OnLoad()与JNI_OnUnload()函数的用途当Android的VM(Virtual Machine)执行到System.loadLibrary()函数时,首先会去执行C组件里的JNI_OnLoad()函数。它的用途有二:(1)告诉VM此C组件使用那一个JNI版本。如果你的*.so档没有提供JNI_OnLoad()函数,V

4、M会默认该*.so档是使用最老的 JNI 1.1版本。由于新版的JNI做了许多扩充,如果需要使用JNI的新版功能,例如JNI 1.4的java.nio.ByteBuffer,就必须藉由JNI_OnLoad()函数来告知VM。(2)由于VM执行到System.loadLibrary()函数时,就会立即先呼叫JNI_OnLoad(),所以C组件的开发者可以藉由JNI_OnLoad()来进行C组件内的初期值之设定(Initialization) 。例如,在Android的/system/lib/libmedia_jni.so档案里,就提供了JNI_OnLoad()函数,其程式码片段为:Java代码:

5、1.2. /#define LOG_NDEBUG 03. #define LOG_TAG MediaPlayer-JNI4.5. jint JNI_OnLoad(JavaVM* vm, void* reserved)6. JNIEnv* env = NULL;7. jint result = -1;8.9. if (vm-GetEnv(void*) &env, JNI_VERSION_1_4) != JNI_OK) 10. LOGE(ERROR: GetEnv failed );11. goto bail;12. 13.14. assert(env != NULL);15.16.17. if

6、(register_android_media_MediaPlayer(env) 0) 18. LOGE(ERROR: MediaPlayer native registration failed );19. goto bail;20. 21.22. if (register_android_media_MediaRecorder(env) 0) 23. LOGE(ERROR: MediaRecorder native registration failed );24. goto bail;25. 26.27. if (register_android_media_MediaScanner(e

7、nv) 0) 28. LOGE(ERROR: MediaScanner native registration failed );29. goto bail;30. 31.32. if (register_android_media_MediaMetadataRetriever(env) 0) 33. LOGE(ERROR: MediaMetadataRetriever native registration failed );34. goto bail;35. 36. result = JNI_VERSION_1_4;37. bail:38. return result;39.40. 此函数

8、回传JNI_VERSION_1_4值给VM,于是VM知道了其所使用的JNI版本了。此外,它也做了一些初期的动作(可呼叫任何本地函数),例如指令:Java代码:1. if (register_android_media_MediaPlayer(env) GetEnv(void*) &env, JNI_VERSION_1_4) != JNI_OK) 7. LOGE(ERROR: GetEnv failed );8. goto bail;9. 10. 11.12.复制代码由于VM通常是多执行绪(Multi-threading)的执行环境。每一个执行绪在呼叫JNI_OnLoad()时,所传递进来的JN

9、IEnv 指标值都是不同的。为了配合这种多执行绪的环境,C组件开发者在撰写本地函数时,可藉由JNIEnv指标值之不同而避免执行绪的资料冲突问题,才能确保所写的本地函数能安全地在Android的多执行绪VM里安全地执行。基于这个理由,当在呼叫C组件的函数时,都会将JNIEnv指标值传递给它,如下:Java代码:1. jint JNI_OnLoad(JavaVM* vm, void* reserved)2.3. JNIEnv* env = NULL;4. if (register_android_media_MediaPlayer(env) MonitorEnter(env, obj) != JN

10、I_OK) 查看是否已经有其他执行绪进入此物件,如果没有,此执行绪就进入该物件里执行了。还有,也可撰写下述指令:if (*env)-MonitorExit(env, obj) != JNI_OK) 查看是否此执行绪正在此物件内执行,如果是,此执行绪就会立即离开。3.registerNativeMethods()函数的用途应用层级的Java类别透过VM而呼叫到本地函数。一般是仰赖VM去寻找*.so里的本地函数。如果需要连续呼叫很多次,每次都需要寻找一遍,会多花许多时间。此时,组件开发者可以自行将本地函数向VM进行登记。例如,在Android的/system/lib/libmedia_jni.so

11、档案里的代码段如下:java代码:1. /#define LOG_NDEBUG 02.3. #define LOG_TAG MediaPlayer-JNI4. static JNINativeMethod gMethods = 5. setDataSource, (Ljava/lang/String;)V,(void *)android_media_MediaPlayer_setDataSource,setDataSource, (Ljava/io/FileDescriptor;JJ)V,(void *)android_media_MediaPlayer_setDataSourceFD,6.

12、prepare, ()V, (void *)android_media_MediaPlayer_prepare,7. prepareAsync, ()V, (void *)android_media_MediaPlayer_prepareAsync,8. _start, ()V, (void *)android_media_MediaPlayer_start,9. _stop, ()V, (void *)android_media_MediaPlayer_stop,10. getVideoWidth, ()I, (void *)android_media_MediaPlayer_getVideoWidth,11. getVideoHeight, ()I, (void *)android_media_MediaPlayer_getVideoHeight,12. seekTo, (I)V, (void *)android_media_MediaPlayer_seekTo,13. _pause, ()V, (voi

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 工作计划

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号