1,什么是NDK和JNI,它们有什么作用和优势?
- NDK是Native Development Kit的缩写,是Android提供的一个工具集,可以让你在Android应用中使用C或C++语言编写部分代码,并将其编译成动态链接库(.so文件),然后在Java层通过JNI调用这些原生代码。
- JNI是Java Native Interface的缩写,是Java提供的一个标准接口,可以让Java代码和其他语言(如C或C++)编写的代码进行交互。JNI定义了一套规范,包括数据类型、函数签名、命名规则等,以保证不同语言之间的兼容性和可移植性。
- NDK和JNI的作用和优势主要有以下几点:
- 提高性能:对于一些计算密集型或者对实时性要求高的任务,使用C或C++语言可以比Java语言更高效地利用CPU资源,减少内存开销和垃圾回收的影响,提升运行速度和响应能力。
- 重用代码:对于一些已经存在的用C或C++语言编写的模块或库,可以通过NDK和JNI直接在Android应用中使用,而不需要重新用Java语言编写,节省开发时间和成本,同时保证代码的一致性和可维护性。
- 调用系统底层:对于一些Java层无法访问或者不方便访问的系统底层功能,例如驱动、硬件、操作系统等,可以通过NDK和JNI调用C或C++语言提供的接口,实现更多的功能和控制。
2,NDK和JNI的使用场景和案例?
- NDK和JNI的使用场景一般是当Java层无法满足需求时,才会考虑使用。因为使用NDK和JNI也会带来一些缺点和风险,例如增加代码复杂度、增加调试难度、增加安全风险等。因此,在使用NDK和JNI之前,应该先评估是否有必要、是否有替代方案、是否有足够的技术能力等。
- NDK和JNI的使用案例有很多,例如:
- 游戏开发:游戏开发通常需要高性能的图形渲染、物理引擎、音频处理等功能,而这些功能往往是用C或C++语言编写的。因此,游戏开发可以通过NDK和JNI调用这些原生代码,实现高质量的游戏体验。
- 图像处理:图像处理也是一个计算密集型的任务,涉及到很多复杂的算法和数据结构。使用C或C++语言可以更好地处理图像数据,实现更快的处理速度和更低的内存消耗。例如,人脸识别、滤镜、美颜等功能都可以通过NDK和JNI实现。
- 文件操作:文件操作涉及到对系统底层的访问和控制,例如文件加密、文件拆分、文件合并等。使用C或C++语言可以更方便地调用系统提供的接口,实现更安全和更高效的文件操作。
3,Android系统服务与JNI
- Android系统服务是一种运行在Android系统中的后台进程,提供了一些核心的功能和接口,供应用层和框架层使用。例如,ActivityManagerService、WindowManagerService、PackageManagerService等。
- Android系统服务通常是用Java语言编写的,但是也有一些是用C或C++语言编写的,例如SurfaceFlinger、MediaServer等。这些原生服务也需要通过JNI和Binder机制与Java层进行通信。
- Android系统服务的架构如下图所示:
4,如何通过JNI与Android系统服务通信
- 通过JNI与Android系统服务通信的步骤大致如下:
- 1.在Java层,定义一个native方法,声明要调用的原生服务的接口
- 2.在C/C++层,实现该native方法,使用JNI API获取原生服务的对象引用、方法ID、字段ID等
- 3.在C/C++层,调用原生服务的方法或访问其字段,使用JNI API转换数据类型和处理异常
- 4.在C/C++层,返回结果给Java层,使用JNI API转换数据类型和处理异常。
例如,假设要通过JNI调用原生SurfaceFlinger服务的dump方法,打印其状态信息。可以参考以下代码:
Java代码:
public class SurfaceFlingerTest { static { System.loadLibrary("surfaceflinger_jni"); } public static void main(String[] args) { dumpSurfaceFlinger(); } public static native void dumpSurfaceFlinger(); }
C/C++代码:
#include <jni.h> #include <gui/SurfaceComposerClient.h> #include <android/log.h> #define LOG_TAG "SurfaceFlingerTest" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) extern "C" JNIEXPORT void JNICALL Java_SurfaceFlingerTest_dumpSurfaceFlinger(JNIEnv *env, jclass clazz) { // get the surface flinger service object reference sp<IBinder> binder = defaultServiceManager()->getService(String16("SurfaceFlinger")); if (binder == nullptr) { LOGI("Failed to get SurfaceFlinger service"); return; } // get the surface flinger interface object reference sp<ISurfaceComposer> composer = interface_cast<ISurfaceComposer>(binder); if (composer == nullptr) { LOGI("Failed to get SurfaceFlinger interface"); return; } // call the dump method of surface flinger and print the result to logcat Vector<String16> args; String8 result; composer->dump(args, result); LOGI("%s", result.string()); }