Background
Although, older versions of OpenCV (ie 2.4) allow Android projects to utilize `SIFT` functionality, the separation of that functionality into `opencv_contrib` makes the task more difficult; integrating a `OpenCV-3.x.x-android-sdk` module into a project leaves you without the ability to use the `SIFT` functionality.
FeatureDetector.create(FeatureDetector.DYNAMIC_SIFT); // Fails
//OpenCV Error: Bad argument (Specified feature detector type is not supported.)
Using External Tools
Although, there are techniques such as [Gouhui Wang's][1] that describe how to build the nonfree portion of OpenCV into an Android project, that process requires external tools. This question is about how to get the same result, but instead leverage the power and convenience of the Android Studio / InteliJ.
Using CMake in Android Studio
Modern Android Studio versions have useful functionality:
Using Android Studio 2.2 and higher, you can use the NDK to compile C and C++ code into a native library and package it into your APK using Gradle, the IDE's integrated build system. Your Java code can then call functions in your native library through the Java Native Interface (JNI)
As indicated in this stackoverflow question and answer concerning building OpenCV with C++ support, it is possible to quickly integrate OpenCV 3.1 (and I suspect other versions) of opencv4android into the C++ build structure that's generated in the new application wizard.
I suspect that someone that understands the details of building projects could utilize Building_OpenCV4Android_from_trunk to answer this question. My expertise in this area is limited, thus, the question.
What specific steps would be required in order to get the nonfree portion of OpenCV to build completely within the native Android Studio build process?
Related
I have gone through all the Android NDK tutorials and built a few simple examples. It seems to me that every example out there from Android Studio revolves around creating a native library attached to an Android application directly. I need to create a native library that is attached to an already existing Android Library. I don't see an example to do this. Is it even possible to hang a native C++ library off an already existing Android Java Library, so the Android Library has access to those native methods, without attaching both libraries (android and native) to a specific application?
Tried in Android Studio to attach a C++ native library to an already existing Android Library, and used CMake as compiler choice, the gradle does not seem to support. The CMakeLists.txt does not seem to be recognized, the "includes" folder is not generated to support the .cpp in the cpp folder, and the native library generates no links I can see to the Android Library methods.
I am a native Android developer, and a client has asked me to re-use his Qt library project in a native Android app. I am really new to Qt development, I mean, I understand C/C++ but have never dealt with Qt development itself, neither the environment or the deployment methods.
I have been looking into these solutions, but I don't get any closer to being able to create an Android project with a Qt library inside with which I can interact.
Similar solutions:
http://thebugfreeblog.blogspot.com/2012/05/embedded-cross-platform-development-for.html
https://developer.android.com/studio/projects/add-native-code#create-sources
My question: How do I export my Qt project to a usable format for my Android project? Any step-by-step guide would be really appreciated.
Thanks!
Assuming your Qt application is only used for its logic (not the GUI side), what you need it to:
Adding JNI to your Qt library for Android
JNI (Java Native Interface) allows creating an interface to link and use native (C++) code from Java. This is used to wrap your C++ code and provide functions visible and usable directly from your Android application
Install the version of Qt you want for Android using Qt's online installer (a checkbox when choosing the version of Qt you want)
Create a JNI interface to allow your application and the library to talk. This is covered in that sample: https://developer.android.com/ndk/samples/sample_hellojni. I would probably recommend creating another C++/JNI library acting as a wrapper for your C++/Qt library. That way you don't contaminate the original library with JNI dependencies.
Integrate your JNI library in your application
Once your have a JNI interface, you have to cross-compile and ship that library with your Android application
Build your native library from Android Studio (after pointing to your Qt libraries and include dir). Alternatively, you can manually build it from Qt Creator (slightly easier) and import only the resulting .so. But that will be painful if your Qt library changes
Package the library (.so), and load it when your application starts. This is also covered in the sample. Once the library is loaded, you will be able to use the JNI functions that you exposed and pass arguments, after some conversion work. Your Android application can also pass a handle to the native library, allowing communication in both ways.
Notes
Be careful to the licensing of your project. Cross-compiling Qt for Android will likely switch to its GPLv3 or Commercial license, versus LGPLv3 without Android.
Qt libraries have to be included in your final pacakge. So they either have to be statically linked against your original library, or dynamically linked, and stored in your APK
You can leverage Qt JNI classes to make the creation of the interface easier, but that is not required: https://doc.qt.io/qt-5/qandroidjniobject.html
Threading can become difficult, as calls to/from JNI have to run from the main thread
I would recommend starting from a working example if you find one, as that whole setup will definitely take some time. I don't know of a complete tutorial covering that, but feel free to share if you find one!
I built a library(.so) that is being called from JNI code in some android app. The JNI code is built using NDK.
If I build the library using android tool-chain, the library works well when called from JNI code.
If I build the library using another tool-chain (used on the same ARM device for none android applications), the library crashes when called from JNI code.
why do we need to use android tool-chain (or NDK) for compiling c/c++ code running in the context of an android app? why not use other tool-chains?
You can use other toolchains, but it requires special care.
Maybe a good starter would be to learn the UBERTC and Linaro Wiki.
The main difference is that NDK compilers are tuned for bionic (Android variant of C runtime libraries). Originally, bionic was a modest subset of Linux runtime. On latest platforms, most of the gap is closed, but now there are many extensions that you probably need.
Also, Android dynamic linker may require (depending on target platform) a set of ELF flags that are automatically delivered by NDK binutils, like PIC, id, and others.
It is quite possible to use arm-linux toolchain to build a statically linked executable that will run on Android, but for a library that must play well on the JNI environment the effort is probably not worth it.
Note that NDK provides tools to create a standalone toolchain, which behaves very similar to other toolchains you may be familiar with. This approach makes it easy to adopt 3rd-party libraries with sophisticated build scripts.
I'm currently working on generating a static C++ library to wrap with JNI use with Android. Using Visual Studio 2015's new support for Android C++ libraries, I was able to generate a dynamic library (.so), and pulled it into Android Studio. Once it was in the proper directory, it was able to link properly, and I was able to call a native method.
However, doing exactly the same thing, but generating a static library (.a), I continuously got UnsatisfiedLinkError, indicating the library was not found by the app. Everything else was controlled for (i.e. same build settings, same location of the library in the file system, etc).
Has anybody else tried doing this? Is there something special that needs to be done to get Android Studio to recognize .as?
Turns out Android Studio just doesn't support Java 8 yet (and with it, support for linking static C++ libraries). So Microsoft is a little ahead of the game with their support for creating those static libraries. Guess it's dynamic linking for the time being.
I can cross-compile any C/C++ application, statically link it Linux libraries and run it on Android. What was the need of an Android-ndk then? Android-ndk limits us to bionic which has a small subset of gnu libc. Isn't it a better idea to straightaway cross-compile applications and run them through Android shell? Is there any limitation to cross-compiling that I can't see? This URL : Can Linux apps be run in Android? answers my question to some extent but eventually leaves me confused and without clarity.
I think this is enough for Android-NDK
The Android NDK is a companion tool to the Android SDK that lets you build performance-critical portions of your apps in native code. It provides headers and libraries that allow you to build activities, handle user input, use hardware sensors, access application resources, and more, when programming in C or C++. If you write native code, your applications are still packaged into an .apk file and they still run inside of a virtual machine on the device. The fundamental Android application model does not change.
The NDK provides:
A set of tools and build files used to generate native code libraries
from C and C++ sources
A way to embed the corresponding native libraries into an application
package file (.apk) that can be deployed on Android devices
A set of native system headers and libraries that will be supported
in all future versions of the Android platform, starting from Android
1.5. Applications that use native activities must be run on Android 2.3 or later.
This thing you can not find in other cross-compilation with arm toolchain..
As mentioned in the link http://developer.android.com/sdk/ndk/index.html NDK is a companion for App development folk to create performance sensitive native code. NDK exposes some of the native implementation of Android which could not be found in the general Linux environments. Some of them include the Android/Bitmap, Android/nativeWindow etc. Using these Android natives applcation can speed up CPU intensive processes like some compression or decompression of images.
Even though the externally cross-compiled executables may run in the Android there no guarantee that versions of the standard library implementaions are the same. NDK provides a easier and Android compatible toolchain and other resources, using which is much easier to application developers than having to find a compatible cross-compiler for their usecase.