2012-01-12 12 views
15

Ho costruito la libreria di Assimp come libreria condivisa. L'ho incluso nel mio progetto Android ndk e funziona bene, ma quando lo carico viene visualizzato il seguente errore: Impossibile caricare la libreria nativa: My-Native-Activity.Caricamento di librerie condivise di terze parti da un'attività nativa di Android

(Forse dovrei aggiungere che la mia attività funziona bene quando la libreria non è inclusa e che ho controllato l'apk e sul dispositivo, la libreria viene aggiunta alla cartella libs e installata sul dispositivo in/data/data/my-app/lib.)

Ho letto molto e sembra che l'unico modo per risolverlo sia caricarli utilizzando System.loadLibrary prima di avviare la mia attività nativa. Penso che preferirei caricarli dinamicamente usando dlopen prima di adottare questo approccio.

Sono corretto nel presupporre che Android non caricherà automaticamente le librerie condivise la mia attività nativa (vale a dire la mia libreria condivisa) dipende da?

Lo vorrei costruire come libreria statica ma era oltre 54 Mb che non funzionerà.

Questo è il mio Android.mk: Ho provato ad aggiungere -lassimp a LOCAL_LDLIBS. Non sono sicuro che sarebbe corretto, ma non ha fatto alcuna differenza.

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 
LOCAL_MODULE      := assimp 
LOCAL_SRC_FILES      := libassimp.so 
include $(PREBUILT_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_MODULE      := native-activity 
LOCAL_SRC_FILES      := main.cpp 
LOCAL_LDLIBS      := -llog -landroid -lEGL -lGLESv2 
LOCAL_STATIC_LIBRARIES    := android_native_app_glue 
LOCAL_SHARED_LIBRARIES    := assimp 
LOCAL_CPPFLAGS      += -march=armv7-a -mfloat-abi=softfp 
LOCAL_CFLAGS    := $(LOCAL_CPPFLAGS) 
TARGET_ARCH_ABI      := armeabi-v7a 
LOCAL_C_INCLUDES   += $(LOCAL_PATH) 
include $(BUILD_SHARED_LIBRARY) 

$(call import-module,android/native_app_glue) 
+0

Sto lavorando a questo problema adesso. Posso vedere la mia libreria .so condivisa che appare nella cartella dei dati. Comunque android_main non viene mai chiamato, se compilo la libreria principale che collega la condivisione non verrà caricata. – Halsafar

+0

Hai provato a lavorare su Android? Potresti inserire qualche codice di esempio su github? Ho problemi con il caricamento dalla directory delle risorse. Assimp consente di implementare il tuo IOSystem e IOStream ma non riesco a farlo funzionare! TXN! –

risposta

19

Subclassing android.app.NativeActivity è il modo più semplice per risolvere questo problema.

package com.you; 

public class MyNativeActivity extends android.app.NativeActivity { 

    static { 
     System.loadLibrary("assimp"); 
    } 
} 

Quindi modificare il AndroidManifest.xml. Sostituire android.app.NativeActivity con MyNativeActivity e rimuovere il tag hasCode="false".

Come nota a margine, Android cerca le dipendenze quando carica una libreria condivisa. Ma lo scopo della ricerca è limitato a /system/lib.

+1

+1 per hasCode = "false" rimozione. Non riuscivo a capire perché non stava costruendo il mio codice java: P –

+0

Immagino che non sapresti se esiste un modo per farlo senza fare riferimento esplicitamente al nome del pacchetto come fatto con il 'pacchetto com .you; 'linea all'inizio? Chiedo perché il codice naturalmente fallisce quando il nome del pacchetto viene modificato forzatamente nel file APK. Noob Java qui. –

0

1: U non poteva usare dlopen, poiché System.loadLibrary è l'unico metodo u caricare una libreria nativa dallo strato Java. 2: il percorso della libreria Ur non sembra corretto, la posizione dovrebbe essere qualcosa di simile a/data/data/urapp/lib/

U bisogno di zippare la libreria ur al tuo file apk, e durante l'installazione, android lo decomprimerà e lo metterà a/data/data/urapp/lib/automaticamente.

La speranza sopra le informazioni è utile per voi.

+0

Grazie per il suggerimento. Non so perché sono andati a quella cartella ma sono stati impacchettati in un file apk come parte di ndk-build, attraverso eclipse (ho controllato all'interno dell'archivio apk per la directory libs). L'apk è stato quindi installato usando adb (di nuovo attraverso eclipse) ed è lì che sono finiti. Ho trovato find usando la shell adb per individuarli ... indagherò ulteriormente. –

+0

Ah, navigato in/data/data/my-app/e fatto un ls -al. la cartella libs contiene un collegamento simbolico a/mnt/asec/my-app/lib. aggiornerò il post principale per riflettere questo. Grazie ancora. –

1

Utilizzare System.loadLibrary è la strada da percorrere.

Android non carica automaticamente le librerie condivise dipendenti per te. Quindi è necessario fare qualcosa di simile:

static { 
    System.loadLibrary("assimp"); // dependency .so first 
    System.loadLibrary("native-activity"); // dependent .so second 
} 

Questo codice va di solito in classe che contiene i metodi Java nativi (cioè metodi definiti con parola chiave native, che mappano fino al codice nativo). Poiché questo codice viene eseguito in un blocco static, viene eseguito quando il classloader Java carica la classe, ad esempio prima che qualsiasi codice nella classe venga effettivamente eseguito.

Non dovrebbe essere necessario aggiungere alcun riferimento a assimp a LOCAL_LDLIBS perché si sta già riferimento assimp tramite la dichiarazione LOCAL_SHARED_LIBRARIES.

This question potrebbe essere rilevante.

+0

L'approccio del blocco statico non funzionerà se non si sottoclasse la classe NativeActivity (che non può essere la via principale da percorrere), ci dovrebbe essere un altro modo per caricare tutte le librerie richieste in fase di esecuzione, penso? – alexleutgoeb

+0

la tua immagine mi fa girare la testa –

6

Si desidera avviare NativeActivity con un'attività java. In questo modo è possibile caricare le librerie condivise prima di NativeActivity.

AndroidManifest.xml:

<application android:label="@string/app_name" android:hasCode="true"> 
    <activity android:name="DummyActivity" 
      android:label="@string/app_name" 
      android:configChanges="orientation|keyboardHidden"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
    <activity android:name="android.app.NativeActivity" 
      android:label="@string/app_name" 
      android:configChanges="orientation|keyboardHidden"> 
     <meta-data android:name="android.app.lib_name" 
       android:value="native-activity" /> 
    </activity> 
</application> 

DummyActivity.java:

package com.example.native_activity; 

import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 

public class DummyActivity extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) {  
     System.loadLibrary("some_shared_lib"); 
     System.loadLibrary("native-activity"); 

     super.onCreate(savedInstanceState); 

     Intent intent = new Intent(DummyActivity.this, android.app.NativeActivity.class); 
     DummyActivity.this.startActivity(intent); 
    } 
} 
+0

Questo è fantastico e funziona per me. Un pelo: la riga 'pacchetto com.example.native_activity; ' è al di fuori del codice e l'ho perso. Risulta che questo è fondamentale. Si compilerà senza di esso, ma ho trascorso l'ora successiva a inseguire perché la classe non si carica! Ho provato a modificare, ma a meno che non cambi almeno sei caratteri, non me lo consente. : - | –

Problemi correlati