8

Tôi đang cố gắng tạo một ứng dụng Android để sử dụng thêm một số thư viện * .so (cụ thể là 'libinterface.so'). Những thư viện này được tạo ra bên ngoài, và được bao gồm như là một sự phụ thuộc bên trong một lớp trình bao bọc được gọi là từ phía Java. Thư viện được lưu vào 'src/main/jniLibs/armeabi-v7a'. Hệ thống bao gồm tất cả các tập tin .so vào ứng dụng được tạo ra.Làm thế nào để sử dụng thêm * .so thư viện trên Android Studio và NDK

Trước đây, tôi đã sử dụng Eclipse cho mục đích này và tôi đã có thể sử dụng thư viện này, nhưng tôi có vấn đề để làm điều này với Android Studio.

Các lỗi được tạo ra là:

/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 

Khi lỗi được ném bởi các mối liên kết, có vẻ liên quan với các bước hòa nhập của thư viện. Trên Eclipse, tôi đã sử dụng tệp 'Android.mk' để bao gồm thư viện mới, nhưng tôi không thể tìm ra cách để làm điều này bằng 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) 

Tôi cố gắng để bao gồm các thư viện với nét gradle này (Lưu ý: Tôi đã bao gồm hỗ trợ cuối cùng JNI và gradle-thực nghiệm 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 
} 
... 

Thư viện này được biên soạn từ bên ngoài sử dụng CMake và công cụ makefile, và nó được biên dịch chéo 'chính xác' cho nền tảng Android (được thử nghiệm với Eclipse và ADT).

tôi đã thực hiện các wrapper như thế này:

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

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

Phần header của thư viện trông như thế này:

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

Cảm ơn trước.

UPDATE:

Sau this example, tôi đã bao gồm một số khối vào script 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" 
       } 
      } 
     } 
    } 
} 

nhưng không hoạt động:

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

Bạn đặt libinterface.so ở đâu? – shhp

+0

Thư viện được lưu trữ trong 'src/main/jniLibs/armeabi-v7a'. Vì nó có thể là thông tin quan trọng, tôi đã cập nhật câu hỏi. – goe

+0

Các thư viện khác có thể được tải chính xác không? – shhp

Trả lời

5

Ok, có thể có hai các vấn đề khác.

Trước tiên, bạn phải chắc chắn rằng thư viện được biên dịch cho đúng kiến ​​trúc. Nếu bạn đang sử dụng thư viện armeabi-v7a, nhưng trình biên dịch đang cố tải một thư viện armeabi thì việc biên dịch sẽ thất bại.

Thứ hai và sau cùng với vấn đề đầu tiên, bạn phải bao gồm các thư viện tùy thuộc vào kiến ​​trúc được sử dụng. Sử dụng cấu hình 'flavours' trong tập lệnh mô-đun build.gradle của bạn.

Trong ví dụ, bạn có thể cố gắng làm một cái gì đó như thế này:

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

Hơn nữa, tôi đề nghị bạn sử dụng 'jniLibs' để lưu trữ các thư viện, bởi vì nó là đường dẫn mặc định cho họ, nhưng sử dụng khác nhau thư mục cho mỗi vòm.

Bạn có thể kiểm tra các ví dụ khác như this.

Hy vọng điều này sẽ hữu ích. Lời chào hỏi.

+1

Cảm ơn bạn rất nhiều. Điều này giải quyết vấn đề của tôi. – goe

+0

Làm cách nào để biên dịch ** thư viện ** chất béo với phương pháp này? – user1056837

Các vấn đề liên quan