8

Próbuję wygenerować aplikację dla systemu Android, aby użyć dodatkowych bibliotek * .so (w szczególności "libinterface.so"). Te biblioteki są generowane zewnętrznie i dołączane jako zależność wewnątrz klasy opakowującej wywoływanej ze strony Java. Biblioteka jest przechowywana w 'src/main/jniLibs/armeabi-v7a'. System zawiera cały plik .so do wygenerowanej aplikacji.Jak korzystać z dodatkowych bibliotek * .so w Android Studio i NDK

Poprzednio używałem Eclipse do tego celu i mogłem korzystać z tej biblioteki, ale mam problemy z tym zrobić w Android Studio.

Generowany jest błąd:

/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 

Gdy błąd jest generowany przez łącznik, wygląda związane z biblioteką etapie integracji. W Eclipse użyłem pliku "Android.mk" do włączenia nowej biblioteki, ale nie mogę znaleźć sposobu, aby to zrobić za pomocą 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) 

Próbuję zawierać bibliotek z tym Gradle definicji (uwaga: mam włączone ostatniego wsparcia JNI i Gradle-eksperymentalny 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 
} 
... 

Biblioteka jest skompilowany z zewnątrz za pomocą CMake i narzędzia makefile i jest poprawnie skompilowany dla platformy Android (testowany z Eclipse i ADT).

I wprowadziły opakowanie tak:

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

i

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

Nagłówek biblioteki wygląda tak:

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

góry dziękuję.

UPDATE:

Po this example, mam włączone niektóre bloki w Gradle skryptu:

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

ale nie działa:

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

Gdzie umieszczasz libinterface.so? – shhp

+0

Biblioteka jest przechowywana w 'src/main/jniLibs/armeabi-v7a'. Ponieważ może to być ważne informacje, zaktualizowałem to pytanie. – goe

+0

Czy inne biblioteki mogą być ładowane poprawnie? – shhp

Odpowiedz

5

Ok, nie może być dwie różne kwestie.

Po pierwsze, musisz mieć pewność, że biblioteka została skompilowana dla poprawnej architektury. Jeśli używasz biblioteki armeabi-v7a, ale kompilator próbuje załadować bibliotekę zbuforowaną, kompilacja się nie powiedzie.

Po drugie, a także po pierwszym wydaniu, należy uwzględnić biblioteki w zależności od używanej architektury. Użyj konfiguracji "flavours" w swoim module build.gradle.

Na przykład, można spróbować zrobić coś takiego:

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

Ponadto, proponujemy użyć „jniLibs” do przechowywania bibliotek, ponieważ jest to domyślna ścieżka dla nich, ale korzystać z różnych folder dla każdego łuku.

Możesz sprawdzić inne przykłady, takie jak this.

Mam nadzieję, że to pomoże. Pozdrowienia.

+1

Dziękuję bardzo. To rozwiązuje mój problem. – goe

+0

Jak można skompilować ** grubą bibliotekę z tym podejściem? – user1056837