无法在本机活动应用程序中加载具有依赖关系的本机共享库

在我的Android应用程序中,我有4个库:

libTemplate.so depends on libPorkholt.so libPorkholt.so depends on libpng15.so depends on liblua.so depends on libopenal.so libpng15.so liblua.so libopenal.so 

如果我写一个小的命令行可执行文件链接到libTemplate和手动调用ANativeActivity_onCreate,它链接和运行就好(如果我指出LD_LIBRARY_PATH到/data/data/com.mycompany.Template/lib)

如果我运行我的应用程序,我得到这个非常有用的错误信息

 E/AndroidRuntime(13214): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mycompany.Template/android.app.NativeActivity}: java.lang.IllegalArgumentException: Unable to load native library: /data/data/com.mycompany.Template/lib/libTemplate.so 

它甚至不会inputANativeActivity_onCreate,所以我唯一的猜测就是它与链接有关

我应该提一下,我正在用这个脚本使用CMake: http : //code.google.com/p/android-cmake/来自己构build库(没有ndk-build)。 我设法编译本地活动示例,所以我知道它的工作原理。

另外,我确保没有库在它的soname中包含一个版本号

我的清单:

 <?xml version="1.0" encoding="utf-8"?> <!-- BEGIN_INCLUDE(manifest) --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mycompany.Template" android:versionCode="1" android:versionName="1.0"> <!-- This is the platform API where NativeActivity was introduced. --> <uses-sdk android:minSdkVersion="9" /> <!-- This .apk has no Java code itself, so set hasCode to false. --> <application android:label="Template Porkholt project" android:hasCode="false"> <!-- Our activity is the built-in NativeActivity framework class. This will take care of integrating with our NDK code. --> <activity android:name="android.app.NativeActivity" android:label="Template Porkholt project" android:configChanges="orientation|keyboardHidden"> <!-- Tell NativeActivity the name of or .so --> <meta-data android:name="android.app.lib_name" android:value="Template" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> <!-- END_INCLUDE(manifest) --> 

Solutions Collecting From Web of "无法在本机活动应用程序中加载具有依赖关系的本机共享库"

由于显然Android不够聪明,无法正确设置LD_LIBRARY_PATH,我设法通过创build一个小的引导程序库来手动加载实际的活动来解决我的问题。 代码如下:

 #include <android/native_activity.h> #include <android/log.h> #include <dlfcn.h> #include <errno.h> #include <stdlib.h> #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Porkholt", __VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "Porkholt", __VA_ARGS__)) #define LIB_PATH "/data/data/@PH_BUNDLE_ID@/lib/" void * load_lib(const char * l) { void * handle = dlopen(l, RTLD_NOW | RTLD_GLOBAL); if (!handle) { LOGE("dlopen(\"%s\"): %s", l, strerror(errno)); exit(1); } return handle; } void ANativeActivity_onCreate(ANativeActivity * app, void * ud, size_t udsize) { LOGI("Loaded boostrap"); load_lib(LIB_PATH "libpng15.so"); load_lib(LIB_PATH "liblua.so"); load_lib(LIB_PATH "libopenal.so"); load_lib(LIB_PATH "libPorkholt.so"); void (*main)(ANativeActivity*, void*, size_t) = dlsym(load_lib(LIB_PATH "lib@PH_APP_TARGET@.so"), "ANativeActivity_onCreate"); if (!main) { LOGE("undefined symbol ANativeActivity_onCreate"); exit(1); } main(app, ud, udsize); } 

我不认为Android会自动加载清单中指定的库以外的库,所以您应该创build一个“虚拟”Java类来加载外部依赖关系,它应该包含:

 static { System.loadLibrary("openal"); System.loadLibrary("lua"); System.loadLibrary("png15"); System.loadLibrary("Porkholt"); System.loadLibrary("Template"); } 

由于这部分是静态的,因此即使未调用其方法,也会在加载类时执行。

这不再影响API 24+(请参阅此处的框架修复)。 但是,如果您需要支持旧版本,请扩展NativeActivity ,而不是在清单文件中引用您的扩展,并添加Sdra答案中提到的static块作为解决方法。

你的Activity可能有一个静态构造函数,它调用System.Load(“libTemplate.so”)。 它应该根据依赖顺序加载其他库。