Android 从 JNI 层调用 jar 文件方法

Call jar file method from JNI layer in Android

我正在尝试在 android 中创建一个带有 JNI 接口的应用程序。

下面是jar文件class:

package testjar;

public class JNICallInterface {
    public native String mymethod();
    public JNICallInterface() {
        // TODO Auto-generated constructor stub
    }

    public String getString(String sd) {
        return "Hello All, I am from JAR";
    }
    public void gotoJNI() {
        System.out.print(mymethod());
    }
}

下面是我的 JNI 文件:

#include <jni.h>

JNIEXPORT jint JNICALL Java_com_testndk_HelloWorld_messageFromNativeCode(
        JNIEnv * env, jobject jObj) {
    return 10;

}
JNIEXPORT jstring JNICALL Java_com_testndk_HelloWorld_textMessageFromNativeCode(
        JNIEnv * env, jobject jObj) {
    jclass clazz = (*env)->FindClass(env, "com/testndk/HelloWorld");
    jmethodID messageMe = (*env)->GetMethodID(env, clazz, "messageMe",
            "(Ljava/lang/String;)V");
    jstring jstr = (*env)->NewStringUTF(env, "This string comes from JNI");
    (*env)->CallVoidMethod(env, jObj, messageMe, jstr);
    return (*env)->NewStringUTF(env,
            "Hello all... I am from JNI method call");

}
JNIEXPORT jstring JNICALL Java_testjar_JNICallInterface_mymethod(JNIEnv * env,
        jobject jObj) {
    jclass clazz1 = (*env)->FindClass(env, "testjar/JNICallInterface");
    jmethodID messageMe1 = (*env)->GetMethodID(env, clazz1, "getString", "(Ljava/lang/String;)V");
    jstring string = (*env)->CallObjectMethod(env, jObj, messageMe1,"ada");
    return (*env)->NewStringUTF(env,string);
}

下面是 LauncherActivity:

package com.testndk;

import testjar.JNICallInterface;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class HelloWorld extends Activity {
    TextView txtHello;

    static {
        System.loadLibrary("HelloWorld");// (“HelloWorld”);
    }

    public native int messageFromNativeCode();

    public native String textMessageFromNativeCode();
    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        txtHello = (TextView) findViewById(R.id.txtHello);
        //int i = messageFromNativeCode();
        String str = textMessageFromNativeCode();
        txtHello.setText(str);
        JNICallInterface in=new JNICallInterface();
        in.gotoJNI();
    }
    public void messageMe(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
}

当我尝试从 JNI 层调用 jar 方法时,出现 "NoSuchMethod" 异常。

是否真的可以从JNI层调用Jar文件方法。我是不是漏掉了什么???

请帮忙!

P.S: 我是 JNI 新手

如果您遵循 fadden 的建议,那么您会发现问题出在方法规范中。 JNICallInterface中的方法是

public class JNICallInterface {
...
    public String getString(String sd) {

但本机代码搜索

jmethodID messageMe1 = (*env)->GetMethodID(env, clazz1, "getString", "(Ljava/lang/String;)V");

这意味着方法返回 void 而现有方法 returns String.

感谢 fadden 和 Zaboj :) 我能够使用正确的签名调用该方法并打印语句。

我的 jar 方法::

public String getString() {
        return "Hello All, I am from JAR";
    }

我的 JNI 调用::

JNIEXPORT jstring JNICALL Java_testjar_JNICallInterface_mymethod(JNIEnv * env,
        jobject jObj) {
    __android_log_print(2, APPNAME, "inside my method");
    jclass clazz1 = (*env)->FindClass(env, "testjar/JNICallInterface");
    __android_log_print(2, APPNAME, "class init");
    jmethodID messageMe1 = (*env)->GetMethodID(env, clazz1, "getString", "()Ljava/lang/String;");
    __android_log_print(2, APPNAME, "found my method");
    jstring string =(jstring)(*env)->CallObjectMethod(env,jObj, messageMe1);
    __android_log_print(2, APPNAME, "called method");
    const char *name = (*env)->GetStringUTFChars(env,string,JNI_FALSE);
    __android_log_print(2, APPNAME, "got string from jar :: %s",name);
    return string;
}

这很好用。包含用于交叉检查的日志语句。