8

Sto provando a generare un'applicazione Android per utilizzare alcune librerie * .so aggiuntive (in particolare 'libinterface.so'). Queste librerie vengono generate esternamente e incluse come dipendenza all'interno di una classe wrapper chiamata dal lato Java. La libreria è memorizzata in "src/main/jniLibs/armeabi-v7a". Il sistema include tutto il file .so nell'app generata.Come utilizzare librerie extra * .so su Android Studio e NDK

In precedenza, stavo usando Eclipse per questo scopo e sono stato in grado di utilizzare questa libreria, ma ho problemi a farlo con Android Studio.

L'errore generato è:

/home/******/Libraries/android-sdk-linux/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/bin/ld: cannot find -linterface 

Come l'errore viene generato dal linker, sembra correlata con la fase di inserimento biblioteca. Su Eclipse, stavo usando un file 'Android.mk' per includere la nuova libreria, ma non riesco a trovare il modo di farlo usando Gradle.

#Android.mk 
LOCAL_PATH := $(call my-dir) 
include $(CLEAR_VARS) 
LOCAL_MODULE := libinterface-prebuilt 
LOCAL_SRC_FILES := prebuilt/libinterface.so 
include $(PREBUILT_SHARED_LIBRARY) 

Sto cercando di includere le librerie con questa definizione Gradle (Nota: ho incluso l'ultimo supporto JNI e Gradle-sperimentale using this tutorial):

... 
android.buildTypes { 
    release { 
     minifyEnabled = false 
     proguardFiles.add(file('proguard-android.txt')) 
    } 
} 

android.ndk { 
    moduleName = "custom_wrapper_jni" 
    cppFlags.add("-I" + file("src/main/jni").absolutePath) 
    cppFlags.add("-I" + file("../Integration/include").absolutePath) // <- New library header include path 
    cppFlags.add("-L" + file("src/main/jniLibs/armeabi-v7a").absolutePath) // <- Path where the library is stored 
    cppFlags.add("-std=c++11") 
    stl = "stlport_static" // Which STL library to use: gnustl or stlport 
    ldLibs.add("log") 

    ldLibs.add("interface") //<- Library to be included 
} 
... 

La libreria viene compilata esternamente utilizzando CMake e strumenti makefile, ed è cross-compilato 'correttamente' per piattaforma Android (testato con Eclipse e ADT).

ho implementato l'involucro in questo modo:

// custom_wrapper_jni.h 
#ifndef ANDROID_JNI_H 
#define ANDROID_JNI_H 

#include <jni.h> 

extern "C" 
{ 
    JNIEXPORT jint JNICALL 
    Java_com_example_goe_android_JniInterface_testFunction(JNIEnv *env, 
                  jobject instance); 
} 
#endif 

e

// custom_wrapper_jni.cpp 
#include <custom_wrapper_jni.h> 

#include "Interface.h" // Header of the included library 

Interface* mInterface = Interface::create(); // Generate the library class instance 

JNIEXPORT jint JNICALL 
Java_com_example_goe_android_JniInterface_testFunction(JNIEnv *env, 
                jobject instance) 
{ 
    LOGI("Test function called in wrapper!"); 
    return mInterface->test(); // Use the instance 
} 

L'intestazione della biblioteca si presenta così:

#ifndef INTERFACE_H__ 
#define INTERFACE_H__ 

#include <string> 

class Interface 
{ 
public: 
    static Interface* create(); 
    virtual ~Interface(){} 


    // Testing function 
    virtual int test() = 0; 

protected: 
    Interface(); 
}; 
#endif // INTERFACE_H__ 

Grazie in anticipo.

UPDATE:

seguito this example, ho incluso alcuni blocchi in sceneggiatura Gradle:

def lib_path = file("src/main/jniLibs").absolutePath 

model { 

    repositories { 
     libs(PrebuiltLibraries) { 
      newlibs { 
       headers.srcDir file("../Integration/include").absolutePath 
       binaries.withType(SharedLibraryBinary) { 
        sharedLibraryFile = file("${lib_path}/${targetPlatform.getName()}/libinterface.so") 
        println "Included libraries: " + file("${lib_path}/${targetPlatform.getName()}/libinterface.so") 
       } 
      } 
     } 
    } 

    android { 
    ... 
    } 

    android.sources { 
     main { 
      jni { 
       dependencies { 
        library "newlibs" linkage "shared" 
       } 
      } 
     } 
    } 
} 

ma non funziona:

Error: org.gradle.nativeplatform.toolchain.internal.CommandLineToolInvocationFailure: Linker failed while linking libcustom_wrapper_jni.so. 
+0

Dove metti libinterface.so? – shhp

+0

La libreria è memorizzata in "src/main/jniLibs/armeabi-v7a". Poiché potrebbe essere informazioni importanti, ho aggiornato la domanda. – goe

+0

È possibile caricare correttamente altre librerie .so? – shhp

risposta

5

Ok, ci potrebbero essere due questioni diverse.

Prima di tutto, è necessario assicurarsi che la libreria sia compilata per l'architettura corretta. Se si sta utilizzando una libreria armeabi-v7a, ma il compilatore sta tentando di caricare una libreria armeabi, la compilazione fallirà.

In secondo luogo e in seguito anche con il primo problema, è necessario includere le librerie in base all'architettura utilizzata. Utilizzare la configurazione 'flavours' nello script build.gradle del modulo.

In esempio, si può provare a fare qualcosa di simile:

android.productFlavors { 
    create("arm") { 
     ndk.with{ 
      abiFilters.add("armeabi") 

      File curDir = file('./') 
      curDir = file(curDir.absolutePath) 
      String libsDir = curDir.absolutePath + "/src/main/jniLibs/armeabi/" 

      ldLibs.add(libsDir + "libinterface.so") 
     } 
    } 
    create("armv7") { 
     ndk.with { 
      abiFilters.add("armeabi-v7a") 

      File curDir = file('./') 
      curDir = file(curDir.absolutePath) 
      String libsDir = curDir.absolutePath + "/src/main/jniLibs/armeabi-v7a/" 

      ldLibs.add(libsDir + "libinterface.so") 
     } 
    } 
} 

Inoltre, vi suggerisco di utilizzare 'jniLibs' per memorizzare le librerie, perché è il percorso predefinito per loro, ma utilizzare diversi cartella per ogni arco.

È possibile controllare altri esempi come this.

Spero che questo aiuti. Saluti.

+1

Grazie mille. Questo risolve il mio problema. – goe

+0

Come si può compilare la ** libreria ** grassa con questo approccio? – user1056837

Problemi correlati