Невозможно загрузить собственную разделяемую библиотеку с зависимостями в приложении для активной активности

В моем приложении для 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 

Он даже не входит в ANativeActivity_onCreate, поэтому я предполагаю только, что это связано с привязкой

Вероятно, я должен упомянуть, что я использую CMake с этим скриптом: http://code.google.com/p/android-cmake/ для создания самих библиотек (без ndk-build). Мне удалось скомпилировать образец собственной активности, поэтому я знаю, что он работает.

Кроме того, я удостоверился, что в библиотеке нет номера версии

Мой манифест:

 <?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) --> ? <?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) --> 

Поскольку, по-видимому, Android недостаточно умен, чтобы правильно установить LD_LIBRARY_PATH, мне удалось решить мою проблему, создав небольшую библиотеку начальной загрузки, которая вручную загружает фактическую активность. Вот код:

 #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 не будет автоматически загружать другие библиотеки, чем те, которые указаны в манифесте, поэтому вы должны создать «фиктивный» java-класс для загрузки внешних зависимостей, он должен содержать:

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

Поскольку этот раздел является статическим, он будет выполняться, когда класс загружается, даже если метод класса не вызван.

Вероятно, ваша активность имеет статический конструктор, который вызывает System.Load («libTemplate.so»). Он должен загружать другие библиотеки в соответствии с порядком зависимости.