【Android】JNI静态与动态注册介绍

简介: 【Android】JNI静态与动态注册介绍

2e98343dd8cf07667b814f62471511ed.jpg

【Android】JNI静态与动态注册介绍

JNI的两种注册机制:静态注册和动态注册.


JNI介绍JNI介绍

JNI(Java Native Interface),即Java本地接口,JNI是Java调用Native 语言的一种特性。通过JNI可以使得Java与C/C++机型交互.


方式

  • 静态注册
  • 动态注册:需要提供Java中Native方法的方法签名和Native层中对应的实现函数。


静态注册静态注册

要求C/C++层的函数名符合某种特定的要求:包含Java中Native方法的目录信息和方法名。


Example

Java

package cn.com.codingce.ndkpractice;
public native String stringFromJNI();

C++

extern "C"
JNIEXPORT jstring JNICALL
Java_cn_com_codingce_ndkpractice_MainActivity_stringFromJNI(JNIEnv *env, jobject thiz) {
    std::string hello = "Hello from C++";
    //crashTest();
    return env->NewStringUTF(hello.c_str());
}

按照以上规则进行命名,在调用到Native的方法时,JVM会去查找是否存在对应函数名的函数,以此实现静态注册。


动态注册动态注册

动态注册相对于静态注册,优点是不再根据特定路径查找函数的实现,带来两个好处:

  • 没有了冗杂的函数名,适用于大型项目开发。
  • 由于不再根据Native函数查找对应的JNI层函数,所以首次调用速度比静态注册快。

开发者需要自行提供Java层和C/C++层中的映射关系。

一种可行的方法是基于JNI重载JNI_OnLoad(),在其中对函数进行动态注册。


Example

Java

package cn.com.codingce.ndkpractice.utils;
public static native void logInit(String logFilePath, String logName, int logfileLevel, int logScreenLevel);


C++

此步骤涉及到如何获取Java函数。

static JNINativeMethod nativeUtilsMethods[] = {
        {"logInit",  "(Ljava/lang/String;Ljava/lang/String;II)V", (void *) localLogInit},
        {"logJni",   "(ILjava/lang/String;)V",                    (void *) logJni},
        {"logClose", "()V",                                       (void *) logClose},
};
static void nativeLogUtilsRegisterNatives(JNIEnv *jniEnv) {
    if (jniEnv == nullptr) {
        return;
    }
    jclass clazz = nullptr;
    do {
        clazz = jniEnv->FindClass("cn/com/codingce/ndkpractice/utils/LogUtils");
        if (clazz == nullptr) {
            diagnosis_assert(!"FindClass LogUtils error!");
            break;
        }
        if (jniEnv->RegisterNatives(clazz, nativeUtilsMethods,
                                    std::extent<decltype(nativeUtilsMethods)>::value) != 0) {
            diagnosis_assert(!"RegisterNatives error!");
            break;
        }
    } while (false);
    if (jniEnv->ExceptionCheck() == JNI_TRUE) {
        jniEnv->ExceptionClear();
    }
    if (clazz != nullptr) {
        jniEnv->DeleteLocalRef(clazz);
    }
}

重载JNI_OnLoad函数,并在其中调用nativeLogUtilsRegisterNatives函数

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *jniEnv{nullptr};
    if (vm->GetEnv((void **) &jniEnv, JNI_VERSION_1_6) != JNI_OK) {
        diagnosis_assert(!"JNI version error!");
        return JNI_EVERSION;
    }
    nativeLogUtilsRegisterNatives(jniEnv);
    return JNI_VERSION_1_6;
}
目录
相关文章
|
5月前
|
Android开发
Android JNI与CAN通信遇到的问题总结
Android JNI与CAN通信遇到的问题总结
137 1
|
5月前
|
Android开发
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
649 1
|
2月前
|
Java Android开发 C++
Android Studio JNI 使用模板:c/cpp源文件的集成编译,快速上手
本文提供了一个Android Studio中JNI使用的模板,包括创建C/C++源文件、编辑CMakeLists.txt、编写JNI接口代码、配置build.gradle以及编译生成.so库的详细步骤,以帮助开发者快速上手Android平台的JNI开发和编译过程。
91 1
|
2月前
|
Java Android开发 UED
安卓scheme_url调端:如果手机上多个app都注册了 http或者https 的 intent。 调端的时候,调起哪个app呢?
当多个Android应用注册了相同的URL Scheme(如http或https)时,系统会在尝试打开这类链接时展示一个选择对话框,让用户挑选偏好应用。若用户选择“始终”使用某个应用,则后续相同链接将直接由该应用处理,无需再次选择。本文以App A与App B为例,展示了如何在`AndroidManifest.xml`中配置对http与https的支持,并提供了从其他应用发起调用的示例代码。此外,还讨论了如何在系统设置中管理这些默认应用选择,以及建议开发者为避免冲突应注册更独特的Scheme。
|
4月前
|
数据库 Android开发 数据安全/隐私保护
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
178 2
|
5月前
|
Android开发 数据安全/隐私保护 iOS开发
ios和安卓测试包发布网站http://fir.im的注册与常用功能
ios和安卓测试包发布网站http://fir.im的注册与常用功能
171 0
ios和安卓测试包发布网站http://fir.im的注册与常用功能
|
4月前
|
存储 数据库 Android开发
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
107 0
|
5月前
|
Java Android开发
Android JNI 调用
Android JNI 调用
31 1
|
5月前
|
XML Android开发 数据格式
Android注册登录页面2
Android注册登录页面
51 2
|
5月前
|
传感器 Java 开发工具
[NDK/JNI系列03] Android Studio集成NDK开发环境
[NDK/JNI系列03] Android Studio集成NDK开发环境
54 0
下一篇
无影云桌面