UnsatisfiedLinkError:找不到本机方法

时间:2014-01-31 12:47:37

标签: java android android-ndk

我知道这个问题到目前为止已被要求死亡,但我读过的解决方案都没有为我工作,所以我想我是否能找到新的答案。

这是Java代码:

private native int nativeVideoPlayerMain(String fileName, int loop,int audioFileType, 
        int skipFrames, int rgb565, int yuvRgbAsm, int skipBidirFrames, int queueSizeMin, int queueSizeMax, int queueSizeTotal, int queueSizeAudio,
        int fastMode, int debugMode, int syncType, int seekDuration, int ffmpegFlags);

包com.example.player和类DemoRenderer。

以下是本机代码定义:

       extern C_LINKAGE int
       Java_com_example_player_DemoRenderer_nativeVideoPlayerMain(JNIEnv* env, 
       jobject obj,
       jstring jfileName, 
       jint loopAfterPlay, 
       jint audioFileType,
       jint skipFrames,
       jint rgb565,
       jint yuvRgbAsm,
       jint skipBidirFrames,
       jint queueSizeMin,
       jint queueSizeMax,
       jint totalQueueSize,
       jint audioQueueSize,
       jint fastMode,
       jint debugMode,
       jint syncType,
       jint seekDuration,
       jint ffmpegFlags)
    {
    jboolean isCopy;

int argc = 1;

    int my_loop_after_play;
    int my_audio_file_type;
    int my_skip_frames;
    int my_rgb_565;
    int my_yuv_rgb_asm;
    int my_skip_bidir_frames;
    int my_queue_size_min;
    int my_queue_size_max;
    int my_total_queue_size;
    int my_audio_queue_size;
    int my_fast_mode;
    int my_debug_mode;
    int my_sync_type;
    int my_seek_duration;
    int my_ffmpeg_flags;

    #ifdef BROOV_C
    const char *fileString = (*env)->GetStringUTFChars(env, jfileName, &isCopy);
    #else
    const char *fileString     = env->GetStringUTFChars(jfileName, &isCopy);
    #endif
    char lclFileName[FILE_NAME_SIZE];

    strncpy(lclFileName, fileString, FILE_NAME_SIZE);

    #ifdef BROOV_C
    (*env)->ReleaseStringUTFChars(env, jfileName, fileString);
    #else
    env->ReleaseStringUTFChars(jfileName, fileString);
    #endif

char *argv[] = { lclFileName };

    my_loop_after_play = loopAfterPlay;
    my_audio_file_type = audioFileType;
    my_skip_frames = skipFrames;
    my_rgb_565 = rgb565;
    my_yuv_rgb_asm = yuvRgbAsm;
    my_skip_bidir_frames = skipBidirFrames;
    my_queue_size_min = queueSizeMin;
    my_queue_size_max = queueSizeMax;
    my_total_queue_size= totalQueueSize;
    my_audio_queue_size= audioQueueSize;
    my_fast_mode = fastMode;
    my_debug_mode = debugMode;
    my_sync_type= syncType;
    my_seek_duration= seekDuration;
    my_ffmpeg_flags = ffmpegFlags;

    return video_player_main(argc, argv, my_loop_after_play, my_audio_file_type, 
                       my_skip_frames, my_rgb_565, my_yuv_rgb_asm, 
                       my_skip_bidir_frames, my_queue_size_min, my_queue_size_max,    
    my_total_queue_size, my_audio_queue_size, my_fast_mode, my_debug_mode,  
    my_sync_type, my_seek_duration, my_ffmpeg_flags);

    }

找到并成功执行此文件中的其他方法,但是这个方法拒绝这样做。我已多次运行ndk-build clean和ndk-build,但无法找到该方法。如果有人有任何建议,请分享:)

编辑: 那是错误信息:

W/dalvikvm(18569): threadid=11: thread exiting with uncaught exception (group=0x41c94ba8)
E/AndroidRuntime(18569): FATAL EXCEPTION: GLThread
E/AndroidRuntime(18569): Process: com.example.player, PID: 18569
E/AndroidRuntime(18569): java.lang.UnsatisfiedLinkError: Native method not found: com.example.player.DemoRenderer.nativeVideoPlayerMain:(Ljava/lang/String;IIIIIIIIIIIIIII)I
E/AndroidRuntime(18569):    at com.example.player.DemoRenderer.nativeVideoPlayerMain(Native Method)
E/AndroidRuntime(18569):    at com.example.player.DemoRenderer.onDrawFrame(DemoRenderer.java:43)
E/AndroidRuntime(18569):    at com.example.player.GLSurfaceView_SDL$GLThread.run(GLSurfaceView_SDL.java:944)
W/ActivityManager(  509):   Force finishing activity com.example.player/.PlayerActivity

更新: 当我试图验证函数确实已加载到其库中时,我发现我不知道这是哪个库。我的意思是:

  • 当我这样做时:grep -R" nativePlayerInit" * -n(这是我在加载时没有问题的同一个文件中的另一个函数)我得到了以下这些:

二进制文件libs / armeabi-v7a / libapplication.so匹配

二进制文件obj / local / armeabi-v7a / libapplication.so匹配

二进制文件obj / local / armeabi-v7a / objs / application / src / native_main.o匹配

  • 当我为nativeVideoPlayerMain执行此操作时,我没有得到静态对象匹配。

  • 最奇怪的是,当我grep原始和工作项目的文件时,我得到了相同的结果。

所以,总而言之:当函数似乎没有被加载到任何静态对象中时,原始项目如何正常工作?它的目录之外的某个地方是否有静态对象?

3 个答案:

答案 0 :(得分:0)

也许你Java_com_example_xformplayer_DemoRenderer_nativeVideoPlayerMain函数缺少一个参数。 你可以使用" javah"创建一个正确的c头文件。

答案 1 :(得分:0)

如果函数没有出现在最终的共享库中,那很可能是构建问题。可能有几个原因:

1)该函数永远不会编译,例如您忘记在LOCAL_SRC_FILES语句中列出其源文件。检查这个的最简单方法是在其中添加“#error BOOO”,然后使用ndk-build重建。它没有看到相应的编译器错误消息,你的源文件没有被编译。

2)该函数已构建,但已从最终的共享库中删除,因为没有人使用它。如果您的函数是静态库的一部分,稍后将其链接到最终的共享库,则会发生这种情况。默认情况下,静态链接器只会从静态库中提取共享库自身功能有效使用的符号及其传递依赖项。防止这种情况的一种方法是使用LOCAL_WHOLE_STATIC_LIBRARIES而不是LOCAL_STATIC_LIBRARIES,阅读$ NDK / docs / SANDROID-MK.TXT以获取更多详细信息。

另一种替代解决方案是将函数定义移动到共享库自己的源文件中。

答案 2 :(得分:0)

好的,该函数抛出了一个不满意的链接错误,因为......这是错误的功能。我不知道怎么做,但我设法复制并完全锁定了错误的函数 - nativeVideoPlayerMain,而不是nativePlayerMain。我正在如此有力地检查的nativeVideoPlayerMain之所以没有在任何库中找到的原因是因为它在#ifdef中并非在两个项目中都是真的。很抱歉浪费每个人的时间:)。