8

我想要生成一个Android应用程序来使用一些额外的* .so库(特别是'libinterface.so')。这些库是从外部生成的,并作为依赖项包含在从Java端调用的包装类中。该库存储在'src/main/jniLibs/armeabi-v7a'中。系统将所有.so文件包含到生成的应用程序中。如何在Android Studio和NDK上使用额外的* .so库

以前,我使用Eclipse来达到这个目的,并且我可以使用这个库,但是我在使用Android Studio时遇到了问题。

产生的错误是:

/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 

由于错误是由连接抛出,它看起来与该库包含步相关。在Eclipse上,我正在使用'Android.mk'文件来包含新库,但我找不到使用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) 

我想包括与此gradle这个定义库(注:我已经包含了过去的JNI支持和gradle这个实验性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 
} 
... 

库使用CMake的编制外和makefile工具,并且它是针对Android平台“正确”交叉编译的(使用Eclipse和ADT进行测试)。提前

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

感谢:

我已经实现了包装这样的:

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

库的头看起来是这样的。

UPDATE:

this example,我已经包括了一些块到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" 
       } 
      } 
     } 
    } 
} 

,但不工作:

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

你把libinterface.so放在哪里? – shhp

+0

该库存储在'src/main/jniLibs/armeabi-v7a'中。因为它可能是重要的信息,我已经更新了这个问题。 – goe

+0

其他.so库可以正确加载吗? – shhp

回答

5

行,有可能是两个不同的问题。

首先,您必须确保该库已针对正确的架构进行编译。如果您正在使用armeabi-v7a库,但编译器正在尝试加载armeabi库,则编译将失败。

其次,在第一个问题之后,您必须根据使用的体系结构包含这些库。 在模块build.gradle脚本中使用'flavours'配置。

在例子中,你可以尝试做这样的事情:

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

此外,我建议你使用“jniLibs”存储库,因为这是他们的默认路径,但使用不同的每个拱门的文件夹。

您可以查看其他例子,如this

希望这会有所帮助。问候。

+1

非常感谢。这解决了我的问题。 – goe

+0

如何用这种方法编译** fat **库? – user1056837