Static initialization of openCV in android is not working - android

I'm trying to add openCV libraries into an Android project to use it in the static initialization way but when I build the application the openCV libraries are not added to the apk.
I put them under the root directory source (called app in Android Studio) in a folder called libs, and then I nested a folder for every target: armeabi, x86, etc.
Do I need to do something else?anybody knows why they are not being added to the apk?
Thanks.

Have you used the Android NDK? Because I think OpenCV is native C/C++ code so you need the NDK in order to accommodate the library into your project.

I finally found the solution to my problem. I just had to put the .so files under src/main/jniLibs and they are added to the apk when bulding. Easier than expected :)

Related

Android Studio C++ NDK library example

I would like to download some working example of Android Studio NDK project with C or C++ which will be compiled to .so library (or APK from which I can extract .so).
I have tried ndkbuild with Android.mk build and also CMake with CMakeLists.txt, official and unofficial tutorials on Windows...
If I try them on android from same app (java), it is working but I want to use NDK in Unity3D on android and I keep getting DllNotFoundException.
I uploaded my Android and Unity projects to github.
First of all, here is a sample Android Project plugin you are looking for.
It's very important to know how to do this yourself.
This used to be hard to do before but the latest Android Studio made it easier to now use C/C++ or generate .so library easily. Update Android Studio to the latest version then follow steps below to create a C++ plugin.
1.Create a new Project in Android Studio
2.Check the Include C++ suport to enable C++.
3.On the Dropdown Menu, check C++ 11 on the C++ Standard drop-down menu. You will need C++ 11 to actually use most useful C++ features. Also, enable exception or frtti if you need them.
That's really it.
When you build the plugin:
The debug library is should be at:
\app\build\intermediates\cmake\debug\obj\
The release library is should be at:
\app\build\intermediates\cmake\debug\obj\
If you only see the debug but not the release version of the plugin, check here for how to make it appear.
Possible reasons you are getting DllNotFoundException on Android:
1.You did not wrap the C/C++ function around extern "C". You must do this for each function in the .cpp file or you do it in the function in the .h file.
2.You put the plugin in the wrong Unity folder.
The armeabi-v7a and x86 plugins generated at <ProjectDirectory>\app\build\intermediates\cmake\release\obj should be placed at Assets\Plugins\Android\libs\armeabi-v7a\ and Assets\Plugins\Android\libs\x86\ in the Unity project.
Make sure to spell these correctly. See this for more information about this.
3.You are loading it incorrectly from the C# side.
Let's say that the name of the plugin is libScreenshot.a, do not include the lib prefix, also do not add the .a when loading it.
[DllImport("Screenshot", CallingConvention = CallingConvention.Cdecl)]
public static extern void takeScreenshot();

How can I create *.so files to Dynamically Link OpenCV for Android?

I'd like to generate libopencv_java.so file from OpenCV 2.4.x source files and libopencv3_java.so from OpenCV 3.x.x source files in order to be able to link OpenCV library dynamically to my Android Application.
Although I can rebuild statically linked *.a library files (e.g. libopencv_core.a & libopencv_imgproc.a) from trunk by means of CMake & MinGW using "Unix makefiles" on a Win64-based development machine for "armeabi-v7a, arm64-v8a, x86 & x86_64" targets; I cannot reproduce the dynamically linked libopencv_java & libopencv3_java.so files and I cannot find any relevant information regarding this issue on OpenCV website or any other knowledge base.
Could anybody please explain to me how to generate these *.so files on a Win64-based development machine by means of CMake & MinGW? I want to make small changes in some of the OpenCV source files and then reproduce everything from scratch.
Using "Unix makefiles" or "MinGW makefiles" or any other configuration doesn't really matter as long as it works properly.
Thanks in Advance
For those who may encounter with a similar problem in the future, I solved this problem by placing newly created *.a files for a specific architecture (armeabi-v7a, arm64-v8a, x86, x86_64 and so on) into their proper place under OpenCV Android prebuilt libraries folder and rebuilding "libopencv_java3.so" under that folder by means of my own Android.mk and Application.mk files. I also used only Python 3 for the code generation phase of "BUILD_opencv_java" and "BUILD_FAT_JAVA_LIB" components, instead of using Python 2 and Python 3 together.
What needs to be done in order to generate the opencv_java is that you need to have python2, java, ant-executable installed in your system. And if i am guessing correct you must be using cmake for generating the .a files. In case your are using some different methods follow the step in the following link:
http://amin-ahmadi.com/2017/08/13/how-to-build-opencv-3-3-x-for-android/
Following the steps mentioned in above liink you should be able to generate the opencv_java file.

Do I need to copy OpenCV native JNI libs to jniLibs directory if I'm using OpenCV manager?

I'm developing (with Android Studio) an Android app that uses OpenCV 3.1.0. I'm using async OpenCV initialization. My questions is: do I need to copy OpenCV native libs (OpenCV-android-sdk/sdk/native/libs) to my jniLibs directory (app/src/main/jniLibs)?
In all the tutorials that I've read about how to setup OpenCV in Android Studio they copy the libraries. But, as I'm using OpenCV manager to access OpenCV libraries externally installed in the device (not static initialization), I think I don't need to copy the libraries. Am I right?
Thanks for your help.
After some time working with OpenCV for Android, I can give an answer to my question:
Async initialization
If you are using async initialization with OpenCV Manager you don't need to copy the native OpenCV libs to your project. Because you are using OpenCV Manager for that:
OpenCV Manager is an Android service targeted to manage OpenCV library
binaries on end users devices. It allows sharing the OpenCV dynamic
libraries between applications on the same device.
More info: OpenCV Manager docs.
Static initialization
According to this approach all OpenCV binaries are included into your application package (this approach is deprecated for the production code).
App without JNI part:
You have to copy the contents of sdk/native/libs into your project directory to folder app/src/main/jniLibs.
App with JNI part:
You need to modify your Android.mk file. After that the OpenCV libraries will be copied to your application jniLibs folder during the JNI build.
More info: Static Initialization docs.
Yes you will be needing to copy the contents of sdk/native/libs for OpenCV into the apps jniLibs directory if you usinf NDK, the java based classes are just a `wrapper to the OpenCV native libraries to make it easier for you to work with OpenCV.
See further official documentation at link provided below: http://docs.opencv.org/2.4/doc/tutorials/introduction/android_binary_package/O4A_SDK.html

Android Unable to load '.so.1' file

Hi I am working on a Android native application.
There is 'abc.so' files which depend on some 'xyz.so.1' file. All of the required files are available in the project structure before building, but the '.so.1' are not a part of the generated .apk file (I checked the apk file by unpacking).
This is causing in a "'java.lang.UnsatisfiedLinkError' Couldnt load 'abc.so.1' from loader dalvik" when trying to run the application.
I dont want to push the .so.1 file as the phone is not rooted and runs on a production build. How do I include the .so.1 files as a part of the APK?
Thank you.
I think you havent got the concept of loading native libraries to Java through JNI.
First you define the native methods in java and do the corresponding implementation in the native and compile it (you have to register the native methods by either 1) following a naming convention 2) registering the native methods in jni_onload...i think you must have done this, if not check http://www.ntu.edu.sg/home/ehchua/programming/android/android_ndk.html)
Next, you have to load the library before any call can be made to native. This has to be done once. You can do it in an activity by defining:
static{
System.loadLibrary("mylib.so");
}
Note while compiling the library you will have got the library name as libXYZ.so, but when loading the library in java the "lib" should be omitted ,just system.loadlibrary(XYZ.so)
If you are using NDK the library would have been already copied to Java project > libs > armeabi folder , if not you have to copy your lib.so there
Now if you have multiple shared libraries , you should load the least dependent lib.so first , followed by second etc i.e.
Static {
System.loadLibrary(independent_lib.so); // should depend on only android libs
System.loadLibrary(next_dependent_lib1.so); //can depend on android libs and independent_lib.so
System.loadLibrary(next_dependent_lib2.so); //can depend on android libs,independent_lib.so,next_dependent_lib1.so
.....
....
..
}
If you jumble up, the VM will not be able to link the libraries and throw a unsatisfied link error.
Lastly, all this .so s will be part of your apk and it will be pushed to the system libs only runtime. Unless its a rooted phone you cannot extract the .so. If you follow the above method you will not need to push any .so to the system. Only build on eclipse/cygwin and run
Hope this helps,
Regards,
Shrish

Calling a function inside .a file in Xamarin

I have a requirement to use C++ code developed using QT inside Xamarin.
The process is like (all done on Windows):
1. Configure and create a static library in QT 5.2
2. Add an Android build kit (MinGW 32) and build the static library for armeabi
3. Use the static library to do P/Invoke inside C# in Xamarin
The problem is that Step 2 above produces a .a file. This is a Linux native object file and I am very sure it will run in Android. How do I use it to perform DllImport and do a P/Invoke? Pardon my ignorence here, I have tried to rename the file to .so and it didn't really help.
Let me know if you need any clarification, your suggestion is very much appreciated.
Thanks, Manoj
You are building a static library. These are meant to be included and loaded at compile time for the programs that use them. What you want it to build a library that can be loaded dynamically, which should end in .so (no you can't just rename it).
You likely need a dynamic library in QT too.

Categories

Resources