I am trying to generate an Android application to use some extra *.so libraries (specifically 'libinterface.so'). Those libraries are generated externally, and included as a dependency inside a wrapper class called from Java side. The library is stored into 'src/main/jniLibs/armeabi-v7a'. The system includes all the .so file into the generated app.
Previously, I was using Eclipse for this purpose and I was able to use this library, but I have problems to do this with Android Studio.
The generated error is:
/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
As the error is thrown by the linker, it looks related with the library inclusion step. On Eclipse, I was using an 'Android.mk' file to include the new library, but I can't find the way to do this using 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)
I am trying to include the libraries with this gradle definition (Note: I have included the last JNI support and gradle-experimental 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
}
...
The library is compiled externally using CMake and makefile tools, and it is cross-compiled 'correctly' for Android platform (tested with Eclipse and ADT).
I have implemented the wrapper like this:
// 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
and
// 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
}
The header of the library looks like this:
#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__
Thanks in advance.
Following this example, I have included some blocks into gradle script:
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"
}
}
}
}
}
but is not working:
Error: org.gradle.nativeplatform.toolchain.internal.CommandLineToolInvocationFailure: Linker failed while linking libcustom_wrapper_jni.so.
Actually inside your JNI folder, android NDK which convert your native code like c or c++ into binary compiled code that is called "filename.so". You cannot read the binary code . so it wil create lib folder inside your libs/armeabi/ filename.so file. Show activity on this post.
You do not need this component if you only plan to use ndk-build. LLDB: the debugger Android Studio uses to debug native code.
Android provides Native Development Kit (NDK) to support native development in C/C++, besides the Android Software Development Kit (Android SDK) which supports Java. [TODO] more. NDK is a complex and advanced topics.
Ok, there could be two different issues.
First, you have to be sure that the library is compiled for the correct architecture. If you are using an armeabi-v7a library, but the compiler is trying to load an armeabi library the compilation will fail.
Second, and following also with the first issue, you have to include the libraries depending the used architecture. Use the 'flavours' configuration in your module build.gradle script.
In example, you can try to do something like this:
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")
}
}
}
Furthermore, I suggest you to use 'jniLibs' to store the libraries, because it is the default path for them, but use different folder for each arch.
You can check other examples like this.
Hope this helps. Greetings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With