如何使用Android NDK调用java函数并从c ++传递参数

时间:2018-03-31 23:55:21

标签: android-ndk java-native-interface

我尝试从我的c ++代码中调用java函数,但应用程序仍然“崩溃”。

首先,我通过JNI调用启动c ++代码,这没有任何问题。然后我让调用的函数执行回调:

#include <jni.h>

extern "C"
JNIEXPORT jstring JNICALL
Java_net_example_folder_Service_startSomething(JNIEnv *env, jobject obj) {
    invoke_class(env);
    return env->NewStringUTF("The End.\n");    //works if I only use this line
}

尝试关注http://www.inonit.com/cygwin/jni/invocationApi/c.html(以及许多其他指南/提示等),我用它来调用java函数:

void invoke_class(JNIEnv* env) {
    jclass helloWorldClass;
    jmethodID mainMethod;

    helloWorldClass = env->FindClass("Java/net/example/folder/helloWorldClass");

    mainMethod = env->GetStaticMethodID(helloWorldClass, "helloWorld", "()V");

    env->CallStaticVoidMethod(helloWorldClass, mainMethod);
}

调用java代码:

package net.example.folder;

import android.util.Log;

public class helloWorldClass {
    public static void helloWorld() {
        Log.e("helloWorldCLass", "Hello World!");
    }
}

c ++代码由后台服务调用。以下是启动它的Activity的功能:

public void startService() {
    Intent i = new Intent(this, Service.class);
    startService(i);
}

这是服务的一部分:

public class SimService extends IntentService {

    ...

    @Override
    protected void onHandleIntent(Intent intent) {
        System.loadLibrary("native-lib");
        startSomething();
    }
}

这一切都有效,但是当我现在将函数'invoke_class'更改为:

void invoke_class(JNIEnv* env) {
    jclass helloWorldClass;
    jmethodID mainMethod;

    helloWorldClass = env->FindClass("net/example/folder/helloWorldClass");

    mainMethod = env->GetStaticMethodID(helloWorldClass, "helloWorld", "([Ljava/lang/String;)V");

    env->CallStaticVoidMethod(helloWorldClass, mainMethod, env->NewStringUTF("some text"));
}

当然是java部分:

package net.example.folder;

import android.util.Log;

public class helloWorldClass {
    public static void helloWorld(String msg) {
        Log.e("helloWorldCLass", msg);
    }
}

有了这个,我会得到前面提到的崩溃。

为什么?如何正确传递参数?

1 个答案:

答案 0 :(得分:2)

符号[用于表示数组(就好像你有String [] msg),从GetStaticMethodID方法中删除它。

您可以查看有关JNI Types and Data Structures here

的更多信息

正如迈克尔所说 - 你应该检查你的本机代码中的java异常,否则你的应用程序将崩溃。您可以使用Exception jni functions执行此操作。例如:

jclass exClass = env->FindClass("some/random/class");
if (exClass == nullptr || env->ExceptionOccurred()) {
    env->ExceptionClear();
    // do smth in case of failure
}