8

Ich versuche eine Android-Anwendung zu generieren, um einige * .so-Bibliotheken (speziell 'libinterface.so') zu verwenden. Diese Bibliotheken werden extern generiert und als eine Abhängigkeit innerhalb einer von Java aufgerufenen Wrapperklasse aufgenommen. Die Bibliothek wird in 'src/main/jniLibs/armeabi-v7a' gespeichert. Das System enthält alle .so-Dateien in die generierte App.So verwenden Sie zusätzliche * .so-Bibliotheken in Android Studio und NDK

Früher habe ich Eclipse für diesen Zweck verwendet und ich konnte diese Bibliothek verwenden, aber ich habe Probleme mit Android Studio.

Der erzeugte Fehler ist:

/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 

Da der Fehler durch den Linker geworfen wird, sieht es damit verbundene mit der Bibliothek Inklusion Schritt. In Eclipse habe ich eine "Android.mk" -Datei verwendet, um die neue Bibliothek aufzunehmen, aber ich finde den Weg dafür nicht mit 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) 

Ich versuche, die Bibliotheken mit dieser gradle Definition aufzunehmen (Anmerkung: Ich habe die letzte JNI Unterstützung enthalten und gradle experimentelle 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 
} 
... 

Die Bibliothek wird erstellt extern CMake verwenden und Makefile-Tools, und es ist Cross-kompiliert für Android-Plattform (getestet mit Eclipse und ADT).

Ich habe den Wrapper wie folgt umgesetzt:

// 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 

und

// 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 
} 

Der Header der Bibliothek sieht wie folgt aus:

#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__ 

Vielen Dank im Voraus.

UPDATE:

Nach this example, ich habe einige Blöcke in gradle Skript enthalten:

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" 
       } 
      } 
     } 
    } 
} 

aber funktioniert nicht:

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

Wo setzen Sie libinterface.so? – shhp

+0

Die Bibliothek ist in 'src/main/jniLibs/armeabi-v7a' gespeichert. Da es wichtige Infos sein könnten, habe ich die Frage aktualisiert. – goe

+0

Können andere .so-Bibliotheken korrekt geladen werden? – shhp

Antwort

5

Ok, es zwei verschiedene Probleme sein könnte.

Zuerst müssen Sie sicher sein, dass die Bibliothek für die richtige Architektur kompiliert ist. Wenn Sie eine armea-v7a-Bibliothek verwenden, der Compiler jedoch versucht, eine armeabi-Bibliothek zu laden, schlägt die Kompilierung fehl.

Zweitens, und folgende auch mit der ersten Ausgabe, müssen Sie die Bibliotheken abhängig von der verwendeten Architektur enthalten. Verwenden Sie die 'flavours' Konfiguration in Ihrem Modul build.gradle Skript.

Im Beispiel können Sie versuchen, etwas zu tun:

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") 
     } 
    } 
} 

Außerdem schlage ich vor, Sie ‚jniLibs‘ zu verwenden, um die Bibliotheken zu speichern, weil es der Standardpfad für sie ist, aber anders verwenden Ordner für jeden Bogen.

können Sie andere Beispiele überprüfen wie this.

Hoffe, das hilft. Schöne Grüße.

+1

Vielen Dank. Dies löst mein Problem. – goe

+0

Wie könnte man ** fat ** library mit diesem Ansatz kompilieren? – user1056837

Verwandte Themen