如何在使用NDK时正确命名本机函数

Jui*_*iCe 1 java-native-interface android android-ndk

我正在尝试运行我的应用程序,但每当我调用本机函数时,它会给我一个错误,程序崩溃.我确定它与我如何在Java或C中命名的东西有关.

这是我对Java函数的调用:

package my.commander;

public class RelayAPIModel {

    public static class NativeCalls {

        static {
            System.loadLibrary( "RelayAPI");
        }

        public native static byte InitRelayJava();

        public native static void FreeRelayJava();
    }
Run Code Online (Sandbox Code Playgroud)

以下是.c文件中的函数:

void Java_my_commander_RelayAPIModel_FreeRelayJava( JNIEnv * env, jobject this ) {
    RelayAPI_DataValid = 0;
    RelayAPI_SetBaud = 0;
    RelayAPI_get = 0;
    RelayAPI_put = 0;
    RelayAPI_flush = 0;
    RelayAPI_delay = 0;
    RelayAPI_initilized = 0;
}


BYTE Java_my_commander_RelayAPIModel_InitRelayJava( JNIEnv *env, jobject obj  ) {
    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

他们在.h文件中:

void Java_my_commander_RelayAPIModel_FreeRelayJava( JNIEnv * env, jobject obj );

BYTE Java_my_commander_RelayAPIModel_InitRelayJava( JNIEnv *env, jobject obj );
Run Code Online (Sandbox Code Playgroud)

这是我的 LogCat:

08-01 09:58:21.933: E/AndroidRuntime(17170): FATAL EXCEPTION: main
08-01 09:58:21.933: E/AndroidRuntime(17170): java.lang.UnsatisfiedLinkError: InitRelayJava
08-01 09:58:21.933: E/AndroidRuntime(17170):    at my.eti.commander.RelayAPIModel$NativeCalls.InitRelayJava(Native Method)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at my.eti.commander.MainMenu.initMain(MainMenu.java:241)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at my.eti.commander.MainMenu.onCreate(MainMenu.java:81)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.os.Handler.dispatchMessage(Handler.java:99)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.os.Looper.loop(Looper.java:130)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at android.app.ActivityThread.main(ActivityThread.java:3683)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at java.lang.reflect.Method.invokeNative(Native Method)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at java.lang.reflect.Method.invoke(Method.java:507)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-01 09:58:21.933: E/AndroidRuntime(17170):    at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

我现在想澄清一下,我已经尝试将C方法名称更改为Java_my_commander_RelayAPIModel_NativeCalls_FreeRelayJavaJava_my_commander_RelayAPIModel_NativeCalls_InitRelayJava.应用程序仍然无法启动,这是LogCat:

08-01 11:22:10.735: E/AndroidRuntime(17441): FATAL EXCEPTION: main
08-01 11:22:10.735: E/AndroidRuntime(17441): java.lang.UnsatisfiedLinkError: InitRelayJava
08-01 11:22:10.735: E/AndroidRuntime(17441):    at my.eti.commander.RelayAPIModel$NativeCalls.InitRelayJava(Native Method)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at my.eti.commander.MainMenu.initMain(MainMenu.java:241)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at my.eti.commander.MainMenu.onCreate(MainMenu.java:81)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.os.Handler.dispatchMessage(Handler.java:99)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.os.Looper.loop(Looper.java:130)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at android.app.ActivityThread.main(ActivityThread.java:3683)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at java.lang.reflect.Method.invokeNative(Native Method)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at java.lang.reflect.Method.invoke(Method.java:507)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-01 11:22:10.735: E/AndroidRuntime(17441):    at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

现在,我认为错误在于上面的代码.如果你们都认为它没有任何问题,我将在这里添加更多信息,以防问题出在其他地方.

我正在创建的这个应用程序使用上面的函数来调用已经使用了一段时间的库.该库以前用于在Palm Pilot程序中调用函数,该程序利用Palm的蓝牙功能.由于Android设备具有不同的蓝牙库/功能,我将代码添加到本机库以调用BACK到java代码,以访问Android设备的蓝牙功能.我不想在这里发布与此相关的所有代码,但如果有人觉得需要发布它,我会.

Sev*_*yev 6

错误消息显示它位于:

my.eti.commander.RelayAPIModel$NativeCalls.InitRelayJava (Native Method)
Run Code Online (Sandbox Code Playgroud)

所以请确保:

  • native方法的声明确实是内部RelayAPIModel类,而不是insude的RelayAPIModel.NativeCalls嵌套类.
  • Java端的包名称与之my.commander相反my.eti.commander

编辑:或者您可以在C方面修复它.如果要在嵌套类中创建本机方法,则其正确名称为:

Java_my_commander_RelayAPIModel_00024NativeCalls_InitRelayJava()
Run Code Online (Sandbox Code Playgroud)

00024是$ character的代码,它是Java内部的嵌套类分隔符.此外,第二个参数(jobject Obj)的含义将是不同的 - 而不是this指针/类指针RelayAPIModel,它将是RelayAPIModel.NativeCalls.您将无法使用它来解析/调用方法RelayAPIModel.


Mic*_*oel 5

您可以使用javah生成具有正确命名的本机文件的.h文件:

javah -jni -classpath bin/classes com.example.app.MyClass
Run Code Online (Sandbox Code Playgroud)