I am trying to add the VTK to my native Android project in AS 3.3. I have installed the NDK r17c. I would like to use some of the VTK functionalities in my native application. Also, I am using gradle 3.3.2 for building my android project and CMake 3.6.4 for building native side of the project. My problem is that I haven't found a suitable tutorial (I am new to Android native development) for importing the VTK into the Android Studio using all building tools that I have described. Is there a way to do that?
Also, I would like to add that I am using Windows 7 OS.
EDIT: I had updated my CMakeLists.txt file with some lines I had found relevant in the official example (https://github.com/Kitware/VTK/tree/master/Examples/Android). I would like to use VTK inside my native-lib library:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
link_directories(src/main/jni/japi src/main/jni/acquisition)
file(GLOB native_SRC
"src/main/jni/japi/*.h"
"src/main/jni/japi/*.cpp"
)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${native_SRC})
file(GLOB acquisition_SRC
"src/main/jni/acquisition/*.h"
"src/main/jni/acquisition/*.cpp"
)
#file(GLOB acquisition_SRC
# "src/main/jni/acquisition/*.h"
# )
add_library( acquisition-lib STATIC ${acquisition_SRC})
#add_library(
# acquisition-lib
#
# STATIC
#
# src/main/jni/acquisition/test-lib.h
# src/main/jni/acquisition/test-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
target_link_libraries( native-lib acquisition-lib )
set(OpenCV_DIR "../opencv/src/sdk/native/jni")
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
target_link_libraries(native-lib ${OpenCV_LIBS})
target_link_libraries(acquisition-lib ${OpenCV_LIBS})
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a")
##ADDED for including the VTK
find_package(VTK COMPONENTS
vtkInteractionStyle
vtkRenderingOpenGL2
vtkRenderingFreeType
vtkTestingCore
vtkTestingRendering
)
include(${VTK_USE_FILE})
target_link_libraries( native-lib ${VTK_LIBRARIES} )
Ok, it took me about a week to get this working, but it paid off. I will list all the things I needed to do to be able to use VTK in my android application.
STEP 1: Building VTK on Linux machine
Because Android is based on the Linux OS, you need to build libraries in .a or .so format. To do this, the easiest thing to do is to build VTK on Linux machine. So you have to install Linux to your machine eather as dual boot or, as in my case, install a virtual machine that runs Linux.
After that, you need to install all the thing needed to download and build VTK for Android. Here is the list of the things you need to download and install to your Linux machine:
Download and install the Android NDK- I downloaded the same version that I am using in my Android Studio - r17c
Download and install the Android SDK , i.e. Android Studio
Download and install ANT
Download and install Java
Download and install CMake - also after I installed it, I needed to run: sudo apt-get update && sudo apt-get install build-essential
Download and install Git
Install OpenGL - I used: sudo apt-get install freeglut3-dev
Define ANDROID_NDK environment variable - point it to unzipped android NDK folder
Define ANT_HOME environment variable - point it to unzipped ANT folder
Define JAVA_HOME environment variable - point it to unzipped Java JRE folder
Define ANDROID_SDK environment variable - point it to the location of Android/Sdk folder
Define CMAKE_HOME environment variable - point it to the location of your installed CMake
Add to PATH enviroment variable: ANT_HOME/bin, JAVA_HOME/bin, ANDROID_SDK/platform-tools, ANDROID_SDK/tools, CMAKE_HOME/bin
After the installation of the all the needed tools above, you need to download the VTK source code using git:
Create an 'vtk' folder somewhere
cd vtk
git clone https://github.com/Kitware/VTK.git
Now, you can go and build the VTK:
mkdir vtk/vtk-android
cd vtk-android
ccmake ../VTK
press c (configure)
press c (configure)
press q (quit)
cmake -DVTK_ANDROID_BUILD=ON -DANDROID_NATIVE_API_LEVEL=23 -DANDROID_ARCH_ABI=arm64-v8a ../VTK - here I defined the 23 api level because that is what I am using in my applicatin. Also, here is where you define the architecture ABI of your targeted devices. My device is arm64-v8a so I am using that. In order to build VTK for other architectures, you will need to build for every each one of them. Also, you can edit this in the next step!
ccmake ../VTK
OPTIONAL: at this point, you can define additional modules you need in your application. If you just skip this step, the modules (.a files) you will get are:
vtkCommonColor, vtkCommonComputationalGeometry, vtkCommonCore,
vtkCommonDataModel, vtkCommonExecutionModel, vtkCommonMath, vtkCommonMisc,
vtkCommonSystem, vtkCommonTransforms, vtkDICOMParser, vtkdoubleconversion,
vtkexpat, vtkFiltersCore, vtkFiltersExtraction, vtkFiltersGeneral,
vtkFiltersGeometry, vtkFiltersHybrid, vtkFiltersModeling, vtkFiltersSources,
vtkFiltersStatistics, vtkfreetype, vtkglew, vtkImagingCore,
vtkImagingFourier, vtkImagingMath, vtkImagingSources, vtkInfovisCore,
vtkInteractionStyle, vtkIOCore vtkIOGeometry, vtkIOImage, vtkIOInfovis,
vtkIOLegacy, vtkIOPLY, vtkIOXML, vtkIOXMLParser, vtkjpeg, vtkjsoncpp,
vtklibxml2, vtklz4, vtklzma, vtkmetaio, vtkParallelCore, vtkpng,
vtkRenderingCore, vtkRenderingFreeType, vtkRenderingOpenGL2,
vtkRenderingVolume, vtkRenderingVolumeOpenGL2, vtksys, vtkTestingRendering,
vtktiff, vtkWrappingTools, vtkzlib
If these modules are not sufficient for you, you need to add some lines to VTK/CMake/vtkAndroid.cmake file because there the build for android is defined. Lines you add must look like:
-DVTK_MODULE_ENABLE_VTK_[name-of-the-module]:STRING=YES
You can find out all possible name-of-the-module values if you press t (toggle) and scroll to VTK_MODULE_ENABLE_VTK_... part of the configuration.
c (configue)
g (generate)
make
Ok, so the build process starts. On my laptop it took ~30mins (I assigned 3GB of RAM to the virtual machine).
STEP 2 : Importing the VTK to the Android Studio
After the build process is finished, you need to copy the folder vtk/vtk-android/CMakeExternals/Install/vtk-android to the your Windows machine.
The folder lib contains the build VTK library as a set of static libraries (.a files), and the folder include contains all the header files of the VTK you neeed to get the VTK working in full.
Now, in your Android Studio project, create a new Android Library module called vtk.
Create the src/main/jni folder and inside that folder copy the lib and include folder described above.
In jni folder crate an vtk-lib.cpp file which will serve as an interface from your Java code to the VTK library. An example may be:
#include <jni.h>
#include <vtkConeSource.h>
extern "C"
JNIEXPORT void JNICALL
Java_link_to_your_java_function(
JNIEnv *env,
jobject /*this*/) {
vtkConeSource *cone = vtkConeSource::New();
cone->SetHeight(3.0);
cone->Delete();
}
In the build.gradle file of your vtk module, add this lines:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
arguments "-DANDROID_CPP_FEATURES=rtti exceptions",
"-DANDROID_STL=gnustl_shared"
abiFilters 'arm64-v8a'
}
}
}
...
externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
}
}
}
After that, to the jni folder add a CMakeLists.txt file which will be used for building the module:
cmake_minimum_required(VERSION 3.4.1)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib/${ANDROID_ABI})
add_library(vtk-common-color STATIC IMPORTED)
set_target_properties(vtk-common-color
PROPERTIES IMPORTED_LOCATION
${LIB_DIR}/libvtkCommonColor-8.90.a)
#53 more libraries from lib folder
add_library( vtk-lib SHARED ${PROJECT_SOURCE_DIR}/vtk-lib.cpp)
target_include_directories(vtk-lib PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(
vtk-lib
-Wl,--start-group -L ${TARGET_OUT}
vtk-common-color
#53 more libraries names
-Wl,--end-group
)
And that's it, voila!
You can
start with the official example on GitHub:
NativeVTK is built around the
Android native interface and does not have any Java code associated with it.
Any unser interface elements would need to be created in C++ using regular
VTK widgets or other OpenGL elements. This is best for applications that
are mainly focused on rendering or visualization with very minimal user
interface. In this example all the key code is in jni/main.cxx and it will
look very much like the regular VTK code you are used to.
It doesn't use Android Studio, and for good! Loading huge amounts of 3rd party native code into Android Studio is both useless and frustrating. It is much better to have such libraries compiled with their native build tools, and only import small modules that require lots of changes and/or interactive debugging.
Related
I am developing an Android app on Android Studio 3.6.1.
I used NDK for the first time today.
When I unzipped my apk, there was a folder for each platform under the lib folder, with a .so file in each folder.
I have a question.
Is it possible to prevent this .so file from being extracted just by extracting apk?
Indeed, reverse-engineering .so files is difficult. However, I don't like the .so file being diverted to steal the return value.
my CMakeLists.txt is...
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
Yes, it is default CMakeLists.txt.
Thanks for your help.
If you can't find it, how would the device find it to run the functions in it? Of course you can't.
And really, if you're worried about that you should see how easily reversible Java and Kotlin are.
I have an Android project with a app/src/CMakeLists.txt file like this
cmake_minimum_required(VERSION 3.4.1)
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
main/cpp/native-lib.cpp )
I also have a app/src/main/cpp/native-lib.cpp file in my project.
When I run ninja in a terminal I get this error
ninja: error: loading 'build.ninja': No such file or directory
I'm not familiar with the NDK and I'm trying to run the project with ninja but I'm not able to find any clear documentation or example.
Android NDK uses CMake to build projects, but instead of run ninja separately, you should run below gradle command to trigger your NDK project build.
./gradlew externalNativeBuild
Internally, CMake will use the ninja build system to compile and link the C/C++ sources for your apps.
As the title suggests I am trying to link a native .so to an android studio project. I have gone through the docs in android developer website and some more articles but unsuccessful in connecting the .so file with the project.
Whenever I try to run the code I get the following error
CMake Error: The following variables are used in this project, but
they are set to NOTFOUND. Please set them or make sure they are set
and tested correctly in the CMake files: testlib
Here is my CMake file
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
add_library(testlib SHARED IMPORTED)
set_property(TARGET testlib PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so")
#find_path(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/RemoteDesktop.h)
find_library(testlib E:/project/Remote_Native/remote_attempt_1/app/libs/armeabi-v7a/libremotedesktop_client.so)
#add_library(remote SHARED IMPORTED)
#set_target_properties(remote PROPERTIES IMPORTED_LOCATION libs/${ANDROID_ABI}/libremotedesktop_client.so )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib}
${testlib})
target_include_directories()
I have four .so files each for arm64, armeabi, armeabi-v7a, x86. I have harcoded the armeabi-v7a lib in the path, android studio is throwing the above mentioned error when I do that. My actual aim is to dynamically load the library based on the chip in the phone. I am pretty sure that my current code is not achieving that.
Here are my queries
How to solve the error that I am getting? I have tried giving both relative and absolute path but to no avail I am getting the same error.
How do I add a .so and a .h file into a native android studio project? That has variations based on the chip on which the code is running?
When I directly add the .h file to the native folder I can reference the classes and functions in that header in my C code but I am unable to run the code. I have a getInstance() method in the .h file. Whenever I call the
getInstance() function it says undefined refernce to getInstance(). What I understand from that is the '.h' file is linked correctly but the definition of the function of the .h files which are actually present in the .so files are not linked. I believe this will be solved if question 1 and 2 are answered.
Is it necessary for all native android projects to have a .mk file? I didn't add one to my project and think it might be one of the cause for the error that I am getting.
You don't need find_library in your case. For log, the library is resolved by NDK for you; for libremotedesktop_client.so, you know the exact path.
Here is the CMakeLists.txt that will work for you:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
add_library(remote SHARED IMPORTED)
set_property(TARGET remote PROPERTY IMPORTED_LOCATION "E:/project/Remote_Native/remote_attempt_1/app/libs/${ANDROID_ABI}/libremotedesktop_client.so")
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
log
remote)
Note that using full path (E:/project…) in CMake script is not the best practice; you probably can express the path to this library somehow relative to the path of your CMakeLists.txt, which is ${CMAKE_CURRENT_SOURCE_DIR}.
1-2). First of all, add set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) at the start of your CMakeLists.txt (just after cmake_minimum_required(...)) to allow another search paths for libraries. After this you can find lib just using standard find_library:
find_library(FOO_LIBRARY
foo # Lib's full name in this case - libfoo.so
PATHS path/to/lib/)
if (NOT FOO_LIBRARY)
message(FATAL_ERROR "Foo lib not found!")
endif()
You can use variable ANDROID_ABI to get particular library version, if directory with libraries organised in this way:
- path/to/lib
- armeabi-v7a
- libfoo.so
- arm64-v8a
- libfoo.so
- x86
- libfoo.so
- x86_64
- libfoo.so
So, search path in this case:path/to/lib/${ANDROID_ABI}/
To include headers in project just use include_directories:
include_directories(path/to/headers)
4). .mk files only needed if you use ndk-build (so you don't need any)
Maybe there is already some answers on this forum about this problem, but i tried a lot of solutions already, and i still didnt solve this problem.
I have to make an android application using C++, wich uses libcurl.
And whatever i do, i can't run my program because it doenst find the library.
In my .cpp, i use this line :
#include <curl/curl.h>
And this is my CMakeLists.txt
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
-lcurl
# Specifies the name of the NDK library that
# you want CMake to locate.
log
-lcurl )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
INCLUDE_DIRECTORIES($/usr/include/)
target_link_libraries( # Specifies the target library.
native-lib
-lcurl
# Links the target library to the log library
# included in the NDK.
${log-lib} )
I used the commands :
sudo aptitude install libcurl4-gnutls-dev
and
sudo aptitude install libcurl-dev
You should rather use the built-in functionality to integrate libcurl:
[...]
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIRS})
add_library(native-lib SHARED src/main/cpp/native-lib.cpp)
target_link_libraries(native-lib ${CURL_LIBRARIES})
As it seems you are cross-compiling for Android, the following will make the curl library that you installed for your Ubuntu available for the compilation (add it before what is above).
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
But it might then be problematic in the linking step, since you installed the library for your Ubuntu and the program you want to compile it with is for Android.
If this does not work, try to have the curl library in your cross-compiling toolset (but I don't know enough about it to tell you how to do it).
I think you need to instruct cmake to find the libcurl dependency.
Please read How_To_Find_Libraries.
And look at find_package and FindCURL module
As a quick-start, add the following to your CMakeLists.txt:
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIRS})
add_library(native-lib SHARED ... )
target_link_libraries(native-lib ${CURL_LIBRARIES})
(even better: use target_include_directories() instead of include_directories()).
I use Qt Creator to compile an Android application. I needed to integrate OpenCV into it, and it took me half a day to configure it properly, so I want to document the steps I took here, in case somebody else ever has to do it.
Edit: For OpenCV 4.x see the answers below. My answer was tested on OpenCV 2.4 only.
Original answer:
First, I downloaded OpenCV-2.4.10-android-sdk, and put into my project directory. It contains static libraries, and link order matters for static libraries for GCC. So you need to order them just so. This is how my .pro file looked in the end ($$_PRO_FILE_PWD_ refers to the project directory):
INCLUDEPATH += "$$_PRO_FILE_PWD_/OpenCV-2.4.10-android-sdk/sdk/native/jni/include"
android {
LIBS += \
-L"$$_PRO_FILE_PWD_/OpenCV-2.4.10-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a"\
-L"$$_PRO_FILE_PWD_/OpenCV-2.4.10-android-sdk/sdk/native/libs/armeabi-v7a"\
-llibtiff\
-llibjpeg\
-llibjasper\
-llibpng\
-lIlmImf\
-ltbb\
-lopencv_core\
-lopencv_androidcamera\
-lopencv_flann\
-lopencv_imgproc\
-lopencv_highgui\
-lopencv_features2d\
-lopencv_calib3d\
-lopencv_ml\
-lopencv_objdetect\
-lopencv_video\
-lopencv_contrib\
-lopencv_photo\
-lopencv_java\
-lopencv_legacy\
-lopencv_ocl\
-lopencv_stitching\
-lopencv_superres\
-lopencv_ts\
-lopencv_videostab
ANDROID_PACKAGE_SOURCE_DIR=$$_PRO_FILE_PWD_/android
}
After that the project will compile but it will fail to run with the error
E/AndroidRuntime(11873): java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1891]: 176 could not load needed library 'libopencv_java.so' for 'libMyProject.so' (load_library[1093]: Library 'libopencv_java.so' not found)
To overcome this, you need to add libopencv_java.so to your APK, and then manually load it from QtActivity.java. That's what the ANDROID_PACKAGE_SOURCE_DIR=$$_PRO_FILE_PWD_/android line at the end was for. Now you need to place libopencv_java.so here:
project_root/android/libs/armeabi-v7a/libopencv_java.so
project_root/android/src/org/qtproject/qt5/android/bindings/QtActivity.java
You can get QtActivity.java from the Android target build directory, in my case the full path was c:\Workspace\build-MyProject-Android_for_armeabi_v7a_GCC_4_9_Qt_5_4_0-Debug\android-build\src\org\qtproject\qt5\android\bindings\QtActivity.java, and just copy it.
Then you find those lines in it:
// now load the application library so it's accessible from this class loader
if (libName != null)
System.loadLibrary(libName);
And load libopencv_java.so before them, so they become:
// This is needed for OpenCV!!!
System.loadLibrary("opencv_java");
// now load the application library so it's accessible from this class loader
if (libName != null)
System.loadLibrary(libName);
Note that you pass opencv_java to System.loadLibrary(), even though the file is libopencv_java.so.
Edit: I forgot to mention, but I already had installed OpenCV Manager on my phone when trying to run one of the samples that come with OpenCV-2.4.10-android-sdk, so I don't know if it's needed or not. In any event, keep it in mind, if it fail even after my steps, you might need to download OpenCV Manager (it's available on the Google Store).
Edit 2: I'm using adt-bundle-windows-x86-20140702, android-ndk-r10d, OpenCV-2.4.10-android-sdk, Qt Creator 3.3.0, and my build target is "Android for armeabi-v7a (GCC 4.9, Qt 5.4.0)".
Edit 3: From Daniel Saner's comment:
In OpenCV 3.x, opencv_java has been renamed to opencv_java3. Also, while I didn't look into the specific changes that might have effected this, the workaround regarding that library in the final step seems to no longer be necessary. The app compiles and runs without the ANDROID_PACKAGE_SOURCE_DIR line
Edit 4: #myk's comment:
Worked for me with OpenCV 3.2. To workaround the build issues with carotene finish the LIBS+ section with: -lopencv_videostab\ -ltegra_hal\ – myk 2 hours ago
For OpenCV 4, sashoalm's approach did not work for me until I adapted it:
Download the Android-Pack and unzip it somewhere. We'll create a qmake-variable OPENCV_ANDROID which points to that directory later.
Add the following snippet to your *.pro-file:
android {
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
isEmpty(OPENCV_ANDROID) {
error("Let OPENCV_ANDROID point to the opencv-android-sdk, recommended: v4.0")
}
INCLUDEPATH += "$$OPENCV_ANDROID/sdk/native/jni/include"
LIBS += \
-L"$$OPENCV_ANDROID/sdk/native/libs/arm64-v8a" \
-L"$$OPENCV_ANDROID/sdk/native/3rdparty/libs/arm64-v8a" \
-llibtiff \
-llibjpeg-turbo \
-llibjasper \
-llibpng \
-lIlmImf \
-ltbb \
-lopencv_java4 \
ANDROID_EXTRA_LIBS = $$OPENCV_ANDROID/sdk/native/libs/arm64-v8a/libopencv_java4.so
} else {
error("Unsupported architecture: $$ANDROID_TARGET_ARCH")
}
}
This will work for the arm64-v8a only. If you happen to build for another architecture (apparently 32-Bit is still the default for Qt#Android), you must change the .../libs/arm64-v8a part of the paths (occurs 3 times) and the same to match your actual target-architecture (the contains(...)-part in the second line of the snippet).
Tell qmake where to find the SDK. Add the following to qmake-call: "OPENCV_ANDROID=/path/to/OpenCV-android-sdk".
e.g., this looks like qmake example.pro "OPENCV_ANDROID=/home/user/OpenCV-android-sdk" from command line.
when you use QtCreator, add "OPENCV_ANDROID=..." to the "Additional arguments"-field. You can find it after enabling the Project-Mode in the Build-section of the android-kit. Expand the qmake-field under Build Steps
Starting from Android android-ndk-r18b, with Qt Creator 4.9.x kits, I could not use the openCV-4.1.1 pre-compiled shared libraries (.so) with Qt Android ABI armeabi-v7a target and ABI arm64-v8a, as Opencv standard is based on GCC, While the NDK-r18b removed gcc and uses clang compiler. ( I am getting
Fatal signal 11 (SIGSEGV), code 1
On initialize calling android_getCpuFeatures() when the application starts)
Thus, openCV shared libs must be compiled from sources for clang in order to be used with Qt Android kits.
This reference Compiling OpenCV on Android from C++ (Without OpenCVManager) was of real help. I would leave a reference here as well for a simple procedure I used under windows 10, to get opencv compiled with NDK 18 (clang) for Qt Android:
Downloaded openCV source code
Downloaded openCV contrib source for selected openCV version
Used cmake for windows
in the unzipped opencv source folder, created a new build folder.
MinGW from Qt installation can generally be used for building, So I used Qt 5.11.x (MinGW 5.3.0 32 bit) command line tool from Qt menu.
from command line, in new build folder, I could generate cmake configuration :
C:\opencv-4.1.1\build> "C:\program files\cmake\bin\cmake" .. -G"MinGW Makefiles"
-DBUILD_SHARED_LIBS=ON
-DANDROID_STL=c++_shared
-DANDROID_ABI="armeabi-v7a with NEON"
-DANDROID_NATIVE_API_LEVEL=23
-DANDROID_TOOLCHAIN=clang
-DCMAKE_TOOLCHAIN_FILE=D:\Qt\android-ndk-r18b\build\cmake\android.toolchain.cmake
-DANDROID_NDK=D:\Qt\android-ndk-r18b
-DANDROID_SDK=C:\Users\moham\AppData\Local\Android\sdk
-DCMAKE_BUILD_TYPE=Debug
-DBUILD_ANDROID_PROJECTS=OFF
-DWITH_OPENCL=ON -DWITH_TBB=ON -DENABLE_NEON=ON
-DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF
-DBUILD_FAT_JAVA_LIB=OFF
Then , C:\opencv-4.1.1\build>\mingw32-make -jx and C:\opencv-4.1.1\build>\mingw32-make install
the result libs can be picked from opencv-4.1.1\build\install folder
Link in Qt Android project:
android {
#opencv
OPENCVLIBS = $$PWD/../opencv-4.1.1\build\install/sdk/native
INCLUDEPATH = $$OPENCVLIBS/jni/include
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
# might need libs to be copied into app's library folder and loaded on start-up, in case android ships older libs??!
ANDROID_EXTRA_LIBS = \
$$OPENCVLIBS/libs/armeabi-v7a/libopencv_core.so \
$$OPENCVLIBS/libs/armeabi-v7a/libopencv_imgproc.so \
$$OPENCVLIBS/libs/armeabi-v7a/libtbb.so
LIBS += -L"$$OPENCVLIBS/libs/armeabi-v7a"\
-lopencv_core -lopencv_imgproc -ltbb
}
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
}
Also, copy the libs to ANDROID_PACKAGE_SOURCE_DIR
Note: If detailed control over cmake configuration is needed, cmake windows gui can be used, while not a must and not tested. AmMIN's procedure is helpful for cmake tool, remember to add flag for shared Android STL.