Integrating LibYUV to my Android Studio Project - android-studio

I was wondering how do I include libyuv library to my Android Studio Project. I have the "libyuv_static.a" file which is a pre-compiled binary file but I did everything to include it in my project. I created a folder inside src/main named jniLibs and puted the binary file inside the folder but in runtime it doesn't load the library and it gives me this:
Caused by: java.lang.UnsatisfiedLinkError: Couldn't load libyuv2rgb
from loader
dalvik.system.PathClassLoader[dexPath=/data/app/com.example.myproject-1.apk,libraryPath=/data/app-lib/com.example.myproject-1]:
findLibrary returned null
. Could someone please share his/her experience.

In order to include a native library into an Android project, you have to get a .so file (shared library), not a .a (static library).
ie. you should end up with src/main/jniLibs/<abi>/libyuv_shared.so with <abi> being armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64 (any architecture your app and lib support).

There is an Android package now: https://github.com/crow-misia/libyuv-android, installable from mavenCentral:
dependencies {
implementation 'io.github.crow-misia.libyuv:libyuv-android:0.25.0'
}
For usage see https://github.com/crow-misia/libyuv-android/blob/main/sample/src/main/java/app/MainActivity.kt

Related

"undefined reference" error from static lib of external parquet project

I want to link expernal 'parquet' project ( https://github.com/apache/arrow/tree/master/cpp ) as part of my current project on Linux.
For this purposes I ran cmake of parquet with such parameters
cd build_parquet
cmake -DCMAKE_BUILD_TYPE=Release -DARROW_PARQUET=ON \
-DBoost_NO_BOOST_CMAKE=TRUE -DBoost_NO_SYSTEM_PATHS=TRUE -DBOOST_ROOT=${BOOST_BUILD_DIR}/include -DBOOST_LIBRARYDIR=${BOOST_BUILD_DIR}/lib/boost -DARROW_BOOST_USE_SHARED=OFF -DBOOST_INCLUDEDIR=${BOOST_BUILD_DIR}/include/boost ..
cmake --build . --config Release
// There are a lot of dependencies except boost, but only boost required to be installed on system, since other could be downloaded and installed by cmake script
Project successfully compiled. I got executable which could launch, generated static libs libarrow.a, libparquet.a, shared libraries libarrow.so, libparquet.so
In my main project I want to use such libraries and I use such commands in cmake to find them
find_path(PARQUET_INCLUDE_DIR NAMES arrow/api.h PATHS ${PARQUET_DIR}/src)
find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.a
PATHS build_parquet/release/Release/ )
find_library(ARROW_LIBRARY_RELEASE NAMES arrow.a
PATHS build_parquet/release/Release/ )
set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Parquet DEFAULT_MSG PARQUET_INCLUDE_DIR
${PARQUET_LIBRARIES_RELEASE } )
That's work okay, libraries and includes are found.
Then I link this libraries to my project
target_link_libraries(${myExe} ${PARQUET_LIBRARIES_RELEASE} ${mySomeOtherLibraries} )
after this I got enormous amount of linker errors such that
libparquet.a(column_writer.cc.o): In function `apache::thrift::transport::TMemoryBuffer::~TMemoryBuffer()':
column_writer.cc:(.text._ZN6apache6thrift9transport13TMemoryBufferD0Ev[_ZN6apache6thrift9transport13TMemoryBufferD5Ev]+0x3): undefined reference to `vtable for apache::thrift::transport::TMemoryBuffer'
.....
so that's what I don't understand much, why lib compiled well in parquet project itself but has a lot of unresolved now, when I use it to link in my own project? Moreover I compiled project for windows and when I did the same things, but with arrow.lib and parquet.lib (instead of libparquet.a and libarrow.a ) things worked fine! I was needed only to put arrow.dll, parquet.dll to executables to run project. But in Linux I've already crashed my head
So, why it doesn't work, what I should do to finally link the project with library ?
Update
I found the problem, I had to link libraries with adding .so files (not only .a files) like this
find_library(PARQUET_LIBRARY_RELEASE NAMES parquet.so parquet.a
PATHS build_parquet/release/Release/ )
find_library(ARROW_LIBRARY_RELEASE NAMES arrow.so arrow.a
PATHS build_parquet/release/Release/ )
set(PARQUET_LIBRARIES_RELEASE ${PARQUET_LIBRARY_RELEASE} ${ARROW_LIBRARY_RELEASE} )
Project is builded. So now the question is, why I need to add .so files to linker (in Windows only static .lib are enough), is it always a case when I build project in Linux ? Is order of linkage important ( .so files first and .a files next ? )
As Uwe wrote in a comment, the https://github.com/apache/parquet-cpp repository is deprecated, and the Parquet C++ library is being developed as part of the Apache Arrow C++ codebase https://github.com/apache/arrow/tree/master/cpp. Can you try building based on that, and if you have trouble can you post on the dev#arrow.apache.org mailing list?
You have succeed to build the project when link with the shared (.so) libraries instead of the static (.a) ones.
(The command find_library actually looks for one library, which name is listed in NAMES option. In your case it found .so library because its name comes before the .a one).
Actually, both shared and static parquet libraries contain the same set of symbols, and both sets are insufficient for link. The difference is that the shared library contains information, where to find remaining symbols (in the thrift library in your case), but the static library doesn't.
For correctly link with the static libraries, you need to list dependent libraries manually.
On Windows .lib file may mean either a static library, or a import file for the shared (.dll) one. It seems that you link with the dynamic one (it has no lib prefix), which succeed like on Linux.

Android NDK, CMake with other libraries

So I am trying to build and test out a CMake with the Android NDK on Android Studio. I can get my library to compile, but it doesn't seem to want to pull any third-party dependencies over. I've been reading through the toolchain and looking for better documentations, with no luck. Can someone tell me if I am missing?
cmake_minimum_required(VERSION 3.4.1)
set(SFML_PATH ${ANDROID_NDK}/sources/sfml)
set(SFML_LIB_PATH ${SFML_PATH}/lib/${ANDROID_NDK_ABI_NAME})
set(SFML_LIB_SYSTEM ${SFML_LIB_PATH}/libsfml-system.so)
set(SFML_LIB_AUDIO ${SFML_LIB_PATH}/libsfml-audio.so)
set(SFML_LIB_GRAPHICS ${SFML_LIB_PATH}/libsfml-graphics.so)
set(SFML_LIB_NETWORK ${SFML_LIB_PATH}/libsfml-network.so)
set(SFML_LIB_WINDOW ${SFML_LIB_PATH}/libsfml-window.so)
set(SFML_LIB_ACTIVITY ${SFML_LIB_PATH}/libsfml-activity.so)
set(SFML_LIB_MAIN ${SFML_LIB_PATH}/libsfml-main.a)
set(SFML_LIBS ${SFML_LIB_SYSTEM} ${SFML_LIB_GRAPHICS} ${SFML_LIB_AUDIO} ${SFML_LIB_WINDOW} ${SFML_LIB_ACTIVITY})
include_directories(${SFML_PATH}/include)
link_directories(${SFML_LIB_PATH})
add_library(native-lib SHARED
src/main/cpp/native-lib.cpp)
target_link_libraries(native-lib log ${SFML_LIBS})
#file(COPY ${SFML_LIBS} DESTINATION ${__android_install_path})
FOREACH(SFML_LIB ${SFML_LIB})
execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${SFML_LIB}" "${LIBRARY_OUTPUT_PATH}/${SFML_LIB}" RESULT_VARIABLE __fileCopyProcess )
MESSAGE("Lib: ${SFML_LIB}")
ENDFOREACH(SFML_LIB)
Above is my CMakeLists.txt. I have done a little hacking to get it to compile with SFML with the paths, as I have not found good documentation with CMake and Android yet.
May you add more info for:
"but it doesn't seem to want to pull any third-party dependencies over."?
this one:
https://github.com/googlesamples/android-ndk/tree/master/hello-libs
has static and shared 3rd party libs, you may try it.
For the shared dependent lib, you will need to pack them into APK, that is done inside gradle, cmake will not do it.
The above example shows that, basically they need to be copied into your app/src/main/jniLibs too so they will be packed into apk, and pushed to your android phone/tablet. At runtime they could be loaded.
I have tried to put a group of libraries into one directory, and use
link_directories(...)
then just put the lib names directly into
target_link_libraries(...)
also works. Make sure you have the right libs for the ABIs you intend to support for your app [looks like you are just building for one ABI].
The process could be little long it will depend on your android skills.
An example could be similar to this process:
Crosscompile sfml.
Create your jni bridge
Generate with cmake the project and compile
Copy your files to android studio. create java loading library code.
I guess that you have crosscompiled sfml and you know how works crosscompiling process, if I am wrong check these link below:
Tutorial:
https://github.com/SFML/SFML/wiki/Tutorial:-Building-SFML-for-Android
Source code:
https://github.com/SFML/SFML
Toolchain:
https://github.com/SFML/SFML/blob/master/cmake/toolchains/android.toolchain.cmake
Changes on your cmake:
add this file
FIND_PACKAGE(SFML required)
In cmake put your SFML build directory and cmake will fills your VARIABLES
automatically for instance this variables:
set(SFML_PATH ${ANDROID_NDK}/sources/sfml)
set(SFML_LIB_PATH ${SFML_PATH}/lib/${ANDROID_NDK_ABI_NAME})
set(SFML_LIB_SYSTEM ${SFML_LIB_PATH}/libsfml-system.so)
set(SFML_LIB_AUDIO ${SFML_LIB_PATH}/libsfml-audio.so)
set(SFML_LIB_GRAPHICS ${SFML_LIB_PATH}/libsfml-graphics.so)
set(SFML_LIB_NETWORK ${SFML_LIB_PATH}/libsfml-network.so)
set(SFML_LIB_WINDOW ${SFML_LIB_PATH}/libsfml-window.so)
set(SFML_LIB_ACTIVITY ${SFML_LIB_PATH}/libsfml-activity.so)
set(SFML_LIB_MAIN ${SFML_LIB_PATH}/libsfml-main.a)
There are two ways to make android studio native apps:
Easy way:
Create JNI bridge:
Crosscompile your cmake script and copy your lib to app/src/main/jniLibs
add library in execution time
code:
try
{
Log.v(LOG_TAG, "adding your library");
System.loadLibrary(your_library);
}
catch(UnsatisfiedLinkError e)
{
Log.e(LOG_TAG,e.getMessage());
}
More complete way (it allows to debug library)
Create your ndk module in gradle
example
android.ndk {
moduleName = "your_library"
cppFlags.add("-fexceptions")
//cppFlags.add("-std=c++11")
//cFlags.add("-fopenmp")
cppFlags.add("-I" + file("src/main/jni").absolutePath)
stl = "gnustl_shared" // Which STL library to use: gnustl or stlport
ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log", "z"])
String libsDir = curDir.absolutePath + "/src/main/jniLibs/armeabi/"
ldLibs.add(libsDir + "your_native_lib.so")
}

linking against library using VS and CMake on windows

I'm new to the world of cmake and linking to libaries. Now for a project I need to include a third party library in the current application. However I'm having problems linking to the library.
Here is what I have:
The library is build in the location D:/qwt-6.1.2, which contains:
the folder /src with the header and source files
the folder /lib which contains (qwt.dll, qwt.ext, qwt.lib, qwtd.dll, qwtd.ext, qwtd.ilk, qwtd.lib and qwtd.pdb.
I have tried to add the following to the cmake file:
add_executable(Demo main.cpp mainwindow.cpp mainwindow.h )
include_directories(D:/qwt-6.1.2/src)
link_directories(D:/qwt-6.1.2/lib)
target_link_libraries(Demo qwt)
The including goes fine since the intellisense of visual studio can the includes that I do, however when I build I get the error:
Error 1 error LNK1104: cannot open file 'qwt.lib'
Does anybody have an idea what I'm doing wrong? I don't care at the moment if it is statically or dynamically linked.

NDK:OpenSSL error" java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libssl.so.1.0.0" needed by "libmyLib.so"

I am trying to build libcurl with openSSL support. I tried using DockerFile and using ubantuimage with that. I am able to compile .so file for libcurl and openSSL. When I try to use those in my android NDK project and load application into device then it gives me error "java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libssl.so.1.0.0" needed by "libmyLib.so"; caused by library "libssl.so.1.0.0" not found". I have put this versioned file where my libcurl.so,libcrypto.so and libssl.so resides. This kind of error comes for every .so I have used depending on order I have included in my Android.mk file. Let me know how to solve this issue. For every .so mentioned above I can see versioned files. Let me know if more detail is required. I am getting error:
java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libssl.so.1.0.0" needed by "libmyLib.so"; caused by library "libssl.so.1.0.0" not found
Android doesn't support versioned .so files, you have to rename it so it ends by .so.
clarification: you should rebuild the library in order to change its name and be able to use it - don't just rename the file itself.

Build boost.thread - lib file not found

I am trying to build the boost.thread library for Visual Studio 9.0. I used bjam to build the lib-files:
bjam toolset=msvc-9.0 variant=release threading=multi link=shared
The compilation succeeded and I got plenty of .lib and .dll files under boost/stage/lib.
Then I added include path and the above lib path to Visual Studio 9.0.
But when I try to compile some program, I always get the following error:
libboost_thread-vc90-mt-s-1_49.lib cannot be opened.
The lib file created by the build has slightly another name:
boost_thread-vc90-mt-1_49.lib
I tried to rename my file to match the expected name, but Visual Studio still cannot find the file.
It seems that the filename beeing seaarched depends on the project option "C/C++ / Code generation / runtime library". I need the option "Multithreaded /MT".
What am I doing wrong?
Thank you in advance.
You're trying to link statically with CRT, but dynamically - with Boost. This is not a good idea, but if you insist, you should define BOOST_ALL_DYN_LINK macro.
Better option would be to select /MD in your project options, or to set "link=static" when building boost.

Resources