JNI介绍(四)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zzw0221/article/details/90612038

JNI分为静态注册和动态注册。前面的文章就是静态注册的例子,此篇会写动态注册的例子。

静态注册:

流程:

         1.编写Java代码,实现Native方法;

          2.利用javah指令生成对应的.h文件;

          3.对.h文件中的声明进行实现;

优点:理解和使用方法简单,使用相关工具按照流程操作就行。

缺点:编写不方便,JNI方法名字必须遵循规则且名字很长。当需要更改类名,包名或者方法适合,需要按照之前方法重新生成头文件,灵活性不高。

动态注册:

优点:灵活性高,更改类名,包名,方法时,只需要对更改模块进行少量修改,效率高。

缺点:对新手不容易理解,会搞错签名,方法,导致注册失败。

举个动态注册的栗子:

1.创建Java类并实现native方法

package cn.zzw.jnidemo2.fromjni;

public class JniTools {
    static {
        System.loadLibrary("myjni");
    }
    public JniTools() {
    }
    public native String getMessageFromJni();
}

2.创建C文件,实现Java中的native方法

jstring cn_zzw_jnidemo2_fromjni_JniTools_getMessageFromJni(JNIEnv* env, jobject thiz)
{
    return (*env)->NewStringUTF(env, "我是zuowei.zhang, 动态注册JNI");
}

3.编写c代码,编写参数映射表,就是需要注册的函数列表,放在JNINativeMethod 类型的数组中,只要有native方法就在这里添加

static const JNINativeMethod g_methods[] = {
    { "getMessageFromJni", "()Ljava/lang/String;", (void*)cn_zzw_jnidemo2_fromjni_JniTools_getMessageFromJni},
};

4.注册native方法

static int register_cn_zzw_jnidemo2_fromjni_JniTools(JNIEnv* env) {
    jclass clazz = (*env)->FindClass(env,"cn/zzw/jnidemo2/fromjni/JniTools");
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if ((*env)->RegisterNatives( env,clazz, g_methods, sizeof(g_methods)/ sizeof(g_methods[0])) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

5. 加载jni,实现JNI_OnLoad方法

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env = NULL;
    jint result = -1;
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    if (register_cn_zzw_jnidemo2_fromjni_JniTools(env) != JNI_TRUE ) {
      return -1;
    }
    //成功
    result = JNI_VERSION_1_4;
    return result;
}

6.详细的c文件如下: 

//
// Created by zuowe on 2019/5/28.
//
#include  <jni.h>

jstring cn_zzw_jnidemo2_fromjni_JniTools_getMessageFromJni(JNIEnv* env, jobject thiz)
{
    return (*env)->NewStringUTF(env, "我是zuowei.zhang, 动态注册JNI");
}

static const JNINativeMethod g_methods[] = {
    { "getMessageFromJni", "()Ljava/lang/String;", (void*)cn_zzw_jnidemo2_fromjni_JniTools_getMessageFromJni},
};

static int register_cn_zzw_jnidemo2_fromjni_JniTools(JNIEnv* env) {
    jclass clazz = (*env)->FindClass(env,"cn/zzw/jnidemo2/fromjni/JniTools");
    if (clazz == NULL) {
        return JNI_FALSE;
    }
    if ((*env)->RegisterNatives( env,clazz, g_methods, sizeof(g_methods)/ sizeof(g_methods[0])) < 0) {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

/*
* System.loadLibrary("lib")时调用
* 如果成功返回JNI版本, 失败返回-1
*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env = NULL;
    jint result = -1;
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    if (register_cn_zzw_jnidemo2_fromjni_JniTools(env) != JNI_TRUE ) {
      return -1;
    }
    //成功
    result = JNI_VERSION_1_4;
    return result;
}

7. 在jni目录下创建Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := myjni

LOCAL_SRC_FILES := ctools.c

include $(BUILD_SHARED_LIBRARY)

8.编译生成.so文件

9.编写app下的build.gradle文件

        ndk{
            moduleName "myjni"
        }
        sourceSets.main{
            jni.srcDirs = []
            jniLibs.srcDir "src/main/libs"
        }

 

9.调用jni

package cn.zzw.jnidemo2;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import cn.zzw.jnidemo2.fromjni.JniTools;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView mTv = findViewById(R.id.mTv);
        JniTools tools=new JniTools();
        mTv.setText(tools.getMessageFromJni());
    }
}

10.结果

完整代码:https://download.csdn.net/download/zzw0221/11212803

猜你喜欢

转载自blog.csdn.net/zzw0221/article/details/90612038
JNI