[NDK/JNI系列01] NDK与JNI的基本概念与使用场景

简介: [NDK/JNI系列01] NDK与JNI的基本概念与使用场景

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());
}

参考资料

相关文章
|
11天前
|
存储 Java C++
[NDK/JNI系列02] JNI的设计原理与数据类型
[NDK/JNI系列02] JNI的设计原理与数据类型
12 0
[NDK/JNI系列02] JNI的设计原理与数据类型
|
11天前
|
缓存 Java API
[NDK/JNI系列05] JNI引用API
[NDK/JNI系列05] JNI引用API
18 0
|
25天前
|
Java Linux 开发工具
NDK与JNI开发(1)ndk_build方式开发
NDK与JNI开发(1)ndk_build方式开发
NDK与JNI开发(1)ndk_build方式开发
|
Java Unix Linux
JNI学习(0)——关于JNI
JNI学习(0)——关于JNI
111 0
JNI学习(0)——关于JNI
|
Linux 编译器 Android开发
【Android NDK 开发】JNI 方法解析 ( JNIEXPORT 与 JNICALL 宏定义作用 )
【Android NDK 开发】JNI 方法解析 ( JNIEXPORT 与 JNICALL 宏定义作用 )
546 0
|
IDE Java 开发工具
NDK 编译的三种方式
通过 Android Studio 默认的方式 创建带有 native 方法的类,build 项目。
311 0
NDK 编译的三种方式
|
Java Android开发 C语言
JNI学习笔记之ndk-build手动编译并集成流程
参考 一天掌握Android JNI本地编程 快速入门Android开发实践:常用NDK命令行参数Secrets of Android.mk JNI JNI是啥? JNI(Java Native Interface):Java本地开发接口,JNI是一个...
1582 0