2012-09-21 2 views
8

In meinem Android App Ich habe 4 Bibliotheken:kann nicht geladen werden native shared Bibliothek mit Abhängigkeiten in einer nativen Aktivität App

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 

Wenn ich eine kleine Befehlszeile ausführbare Datei, die gegen libtemplate Links schreiben und ANativeActivity_onCreate manuell aufrufen, es verbindet und läuft ganz gut (wenn ich LD_LIBRARY_PATH /data/data/com.mycompany.Template/lib Punkt)

wenn ich meine Anwendung ausführen ich diese sehr nützliche Fehlermeldung:

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 

Es gibt nicht einmal ANativeActivity_onCreate, also meine einzige Vermutung ist, dass es etwas mit Verknüpfung zu tun hat

Ich sollte wahrscheinlich erwähnen, dass ich CMake mit diesem Skript verwende: http://code.google.com/p/android-cmake/, um die Bibliotheken selbst zu bauen (ohne ndk- bauen). Ich habe es geschafft, das native-activity-Sample damit zu kompilieren, also weiß ich, dass es funktioniert.

Auch ich stellte sicher, dass keine Bibliothek eine Versionsnummer in seiner soname enthält

Mein 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) --> 
+0

Was ist Ihr Manifest? – Ken

+0

Ich habe es gerade oben gepostet :) –

+0

Könnten Sie mich wissen lassen, wie Sie "ANativeActivity_onCreate" manuell aufrufen? Hast du das in C-Code gemacht? – echo

Antwort

10

Da Android offenbar nicht schlau genug ist, um einen LD_LIBRARY_PATH richtig zu setzen, konnte ich mein Problem lösen, indem ich eine kleine Bootstrapper-Bibliothek erstellte, die die eigentliche Aktivität manuell lädt. Hier ist der 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/@[email protected]/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 "[email protected][email protected]"), "ANativeActivity_onCreate"); 
    if (!main) 
    { 
     LOGE("undefined symbol ANativeActivity_onCreate"); 
     exit(1); 
    } 
    main(app, ud, udsize); 
} 
+0

Danke da_petcu21. Das Laden von Bibliotheken in der JVM mit nativem Code ist ein wertvoller Beitrag;) ... +1 – Sdra

+0

Danke für den Code! – jhasse

+0

Sagen Sie, dass die einzige Möglichkeit, eine native Aktivität zum Laden von .so-Bibliotheken zu machen, darin besteht, eine zweite native Aktivität zu veranlassen, die Bibliotheken manuell zu laden und die erste native Aktivität zu starten? Wenn nicht, könnten Sie näher erläutern, wie Ihre Lösung funktioniert? Ich habe dieses Problem schon seit einiger Zeit ohne viel Glück bearbeitet. –

0

Ihre Aktivität wahrscheinlich hat einen statischen Konstruktor, System.Load nennt ("libTemplate.so"). Es sollte die anderen Bibliotheken entsprechend der Abhängigkeitsreihenfolge laden.

5

Ich glaube nicht, Android automatisch Bibliotheken andere als die im Manifest spezifizierte laden, so dass Sie eine „Dummy“ Java-Klasse erstellen sollten externe Abhängigkeiten zu laden, soll es enthalten:

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

Seit Dieser Abschnitt ist statisch und wird beim Laden der Klasse ausgeführt, selbst wenn die Methoden nicht aufgerufen werden.

+0

Ja, das war das Problem, aber ich habe es geschafft, es ohne Java zu lösen. Ich werde meine Lösung posten –

1

Dies beeinflusst nicht länger der API 24+ (siehe Rahmen fix here). Wenn Sie jedoch ältere Versionen unterstützen müssen, erweitern Sie NativeActivity, beziehen Sie sich stattdessen auf Ihre Erweiterung in der Manifestdatei, und fügen Sie den static-Block hinzu, der in Sdra's answer als Problemumgehung erwähnt wird.

Verwandte Themen