so库调用java方法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

JNI调用Java方法的流程是先通过类名找到类,然后再根据方法名找到方法的id,最后就可以调用这个方法了。如果是调用Java中的非静态方法,那么需要构造出类的对象后才能调用它。下面的例子演示了如何在JNI中调用Java的静态方法,以及非静态方法

操作流程

新建JniTest类,代码如下

public class JniTest {
    
    
    static {
    
    
        System.loadLibrary("jni-test");  //加载libjni-test.so库
    }

    public native String callJniMethod();  //声明本地方法,调用so库代码

    public static void staticMethodCalledByJni(String msgFromJni) {
    
        //静态方法
        Log.d("test","staticMethodCalledByJni,msg:" + msgFromJni);
    }

    public String methodCalledByJni(String msgFromJni) {
    
       //非静态方法
        Log.d("test","methodCalledByJni,msg:" + msgFromJni);
        return "methodCalledByJni!!!";
    }
}

在JNI中实现callJniMethod方法,并调用上面定义的静态方法和非静态方法。在项目
app目录下新建jni文件夹,在jni文件夹中创建test.c文件,代码如下:

#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <android/log.h>

void
callJavaStaticMethod(JNIEnv *env, jobject thiz) {
    
    
     //1. 获取JniTest类的Class引用
    jclass clazz = (*env)->FindClass(env,"com/habit/jnitest/JniTest");
    if (clazz == NULL) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "test", "find class JniTest error!\n");
        return;
    }
    //2.获取JniTest类的staticMethodCalledByJni方法的id
    jmethodID id = (*env)->GetStaticMethodID(env,clazz, "staticMethodCalledByJni", "(Ljava/lang/String;)V");
    if (id == NULL) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "test", "find method staticMethodCalledByJni error!\n");
    }
    jstring msg = (*env)->NewStringUTF(env,"msg send by callJavaStaticMethod in test.c.");
    //3.调用java的staticMethodCalledByJni方法
    (*env)->CallStaticVoidMethod(env,clazz, id, msg);
}

jstring
callJavaMethod(JNIEnv *env, jobject thiz) {
    
    
     //1. 获取JniTest类的Class引用
    jclass clazz = (*env)->FindClass(env,"com/habit/jnitest/JniTest");
    if (clazz == NULL) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "test", "find class JniTest error!\n");
        return "";
    }
    //2. 获取类的默认构造函数ID
    jmethodID construct_id = (*env)->GetMethodID(env,clazz, "<init>", "()V");
    if (construct_id == NULL) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "test", "find method construct_id error!\n");
    }
    //3.实例化这个对象
    jobject jobj = (*env)->NewObject(env,clazz, construct_id);
    if (jobj == NULL) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "test", "NewObject jobj error!\n");
    }
    //4.获取JniTest类的methodCalledByJni方法的id
    jmethodID id = (*env)->GetMethodID(env,clazz, "methodCalledByJni", "(Ljava/lang/String;)Ljava/lang/String;");
    if (id == NULL) {
    
    
        __android_log_print(ANDROID_LOG_ERROR, "test", "find method methodCalledByJni error!\n");
    }
    jstring msg = (*env)->NewStringUTF(env,"msg send by callJavaMethod in test.c.");
    //5.调用java的methodCalledByJni方法
    return (jstring)(*env)->CallObjectMethod(env,jobj, id, msg);
}

jstring
Java_com_habit_jnitest_JniTest_callJniMethod(JNIEnv *env, jobject thiz) {
    
    
    //调用静态方法
    callJavaStaticMethod(env,thiz);
    //调用非静态方法
    jstring str = callJavaMethod(env,thiz);
    char* str2 = (char*) (*env)->GetStringUTFChars(env,str, 0); //string 转char*
     __android_log_print(ANDROID_LOG_ERROR, "test", "%s\n",str2);
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}

备注:
(1)FindClass方法的其中一个参数是“包名/类名”,要改成自己的包名和类名。
(2)jni中对应java的方法名是Java_包名_类名_方法名,下方代码中的Java_com_habit_jnitest_JniTest_callJniMethod要改成自己项目的包名。

在jni文件夹创建Android.mk文件,文件内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#加入这句可以使得so文件打印日志
LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog

#生成so库的名称,生成后会添加前缀lib
LOCAL_MODULE    	:= jni-test
LOCAL_SRC_FILES		:= test.c

include $(BUILD_SHARED_LIBRARY)

生成so库,并将so库剪切到app\src\main\jniLibs文件夹中。

在这里插入图片描述

生成so库的操作步骤参考AndroidStudio生成so库

在MainActivity中调用so库的方法,代码如下:

public class MainActivity extends AppCompatActivity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        JniTest jniTest = new JniTest();
        System.out.println(jniTest.callJniMethod());
    }
}

运行程序,程序正常运行的日志如下:
在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/weixin_46092051/article/details/131653138