SDL_Mixer 和 Android 上的 SMPEG2 运行时链接错误

Runtime linking error with SDL_Mixer and SMPEG2 on Android

我设法解决了之前 link 由 android api 21 引起的 NDK 问题,并设法构建并运行 SDL_TTF很容易,但是使用 SDL_Mixer 我遇到了另一个运行时不满意 link 错误,其中应用程序无法 link smpeg2 lib 与 SDL2_Mixer。这次我看不出它与 api 级别有什么关系,并且尝试了所有我能想到的方法,检查了每个 makefile 并对每个版本进行了三重检查。

我使用 SDL_Mixer 2.0.0 和 smpeg2-2.0.0 作为它唯一的依赖。 Smpeg2 位于 jni/ 文件夹中,整个东西是在没有编译器咳嗽的情况下构建的。

我下载了 SDL_Mixer 2.0.0 源代码并将其放在 jni/ 文件夹中,将 smpeg2-2.0.0 从它的 external/ 文件夹复制到 jni/ 并从 mixer makefile 设置为仅构建 smpeg2。我编辑 src/Android.mk 以查看混音器源并获取共享库,然后编辑 SDLActivity 以拉取 SDL2_mixer 库。 SDL_TTF 就是这样工作的。

libsmpeg2.so 确实存在于 libs/ 文件夹中,所以我不明白它是如何找不到它的。

我正在使用 android-19 作为 NDK 的构建目标,编译器没有给出任何警告或错误。

01-22 18:17:43.760: D/dalvikvm(22101): Trying to load lib /data/data/com.kebabkeisari.peli/lib/libSDL2.so 0x41d88e78
01-22 18:17:43.760: D/dalvikvm(22101): Added shared lib /data/data/com.kebabkeisari.peli/lib/libSDL2.so 0x41d88e78
01-22 18:17:43.760: D/dalvikvm(22101): Trying to load lib /data/data/com.kebabkeisari.peli/lib/libSDL2_mixer.so 0x41d88e78
01-22 18:17:43.765: W/dalvikvm(22101): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lorg/libsdl/app/SDLActivity;
01-22 18:17:43.765: W/dalvikvm(22101): Class init failed in newInstance call (Lcom/kebabkeisari/peli/Ribale;)
01-22 18:17:43.765: D/AndroidRuntime(22101): Shutting down VM
01-22 18:17:43.765: W/dalvikvm(22101): threadid=1: thread exiting with uncaught exception (group=0x410c52a0)
01-22 18:17:43.765: E/AndroidRuntime(22101): FATAL EXCEPTION: main
01-22 18:17:43.765: E/AndroidRuntime(22101): java.lang.ExceptionInInitializerError
01-22 18:17:43.765: E/AndroidRuntime(22101):    at java.lang.Class.newInstanceImpl(Native Method)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at java.lang.Class.newInstance(Class.java:1319)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.app.Instrumentation.newActivity(Instrumentation.java:1057)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2015)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.app.ActivityThread.access0(ActivityThread.java:140)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.os.Looper.loop(Looper.java:137)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at android.app.ActivityThread.main(ActivityThread.java:4898)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at java.lang.reflect.Method.invokeNative(Native Method)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at java.lang.reflect.Method.invoke(Method.java:511)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at dalvik.system.NativeStart.main(Native Method)
01-22 18:17:43.765: E/AndroidRuntime(22101): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1892]:  1952 could not load needed library 'libsmpeg2.so' for 'libSDL2_mixer.so' (load_library[1094]: Library 'libsmpeg2.so' not found)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at java.lang.Runtime.loadLibrary(Runtime.java:370)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at java.lang.System.loadLibrary(System.java:535)
01-22 18:17:43.765: E/AndroidRuntime(22101):    at org.libsdl.app.SDLActivity.<clinit>(SDLActivity.java:51)
01-22 18:17:43.765: E/AndroidRuntime(22101):    ... 15 more

您需要以反向依赖顺序加载库。即如果libSDL2_mixer.so依赖于libsmpeg2.so,则需要先加载libsmpeg2.so,然后才能尝试加载libSDL2_mixer.so.

也就是说,为了加载库,你需要这样做:

System.loadLibrary("smpeg2");
System.loadLibrary("SDL2_mixer");

IIRC 这已在某些最新版本的 Android 中得到修复,但为了让旧版本也能正常工作,您需要一次明确地加载它们。