Can't load native shared library with dependencies in a native activity app

android, android-ndk, linker, native-activity

Solution

Since apparently Android isn't smart enough to set a LD_LIBRARY_PATH correctly, I managed to solve my problem by creating a small bootstrapper library that manually loads the actual activity. Here's the code:

#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 bootstrap");
    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);
}

Problem

In my Android app I have 4 libraries: ``` 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 ``` If I write a small command line executable that links against libTemplate and manually call ANativeActivity_onCreate, it links and runs just fine (if I point LD_LIBRARY_PATH to /data/data/com.mycompany.Template/lib) If I run my app I get this very useful error message: ``` 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 ``` It doesn't even enter ANativeActivity_onCreate, so my only guess is that's it has something to do with linking I should probably mention that I'm using CMake with this script: http://code.google.com/p/android-cmake/ to build the libraries myself (without ndk-build). I managed to compile the native-activity sample with it, so I know it works. Also, I made sure no library contains a version number in its soname My 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) --> ```

Original source