Wrapp existing library (.so) in jni for android app - android

I wanna realize this idea. I spent several days searching for information, but could not find anything. All tutorials say how to write my own library with JNI, but how to wrap already existing? I need just simple tutorial step by step (and why? if it possible). So I wanna start create native android application.
What I have :
I create C++ library in QTCreator by tutorial from youtube: simple library on C++ (.so) with headers (.h) which do simple cout in console:
Not compiled code mylib.cpp:
#include "mylib.h"
MyLib::MyLib() { }
void MyLib::Test() {
qDebug() << "Hello from our DLL";
// .so
}
Header mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
#include "mylib_global.h"
#include <QDebug>
class MYLIBSHARED_EXPORT MyLib
{
public:
MyLib();
void Test();
};
#endif // MYLIB_H
and mylib_global.h (I think it does't matter)
So after build I have myLib.so.
And now I need wrap it in my android app. So I don't understand what I need to do for it.
I'm develop in Android Studio. And what I know:
Create in java package LibWrappClass with native method - something like "simplePrint()":
public native void simplePrint();
I need to create in /src/main folder "jni". Create Android.mk, myLibWrapper.h and myLibWrapper.cpp. But I don't understand what I need to write in Android.mk for connect my myLib.so to "myLibWrapper.h", and where should I put my library with headers. Can anyone help?

After adding the native method in your java code, You simply build the project. Now you need to move to the location where the class files are written by your IDE. Since you use Android Studio, it must be somewhere your project folder with path
out/production/YourModuleName
Open the location in commandline and run the javah command to generate the header file for your native function
javah -d <your jni folder path> <com.YourPackage.YourClass>
The class YourClass should be where you have declared the native method. This command will create a header file with name something like com_YourPackage_YourClass.h with a function declaration looks like
JNIEXPORT void JNICALL Java_com_YourPackage_YourClass_simplePrint
(JNIEnv *, jobject);
Implement this function in a C/C++ file with whatever operations you have to perform on jni side.
Then, Define the Android.mk file, In this case it will be something like
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lib
LOCAL_SRC_FILES := lib.c
include $(BUILD_SHARED_LIBRARY)
If you have multiple source files add them in LOCAL_SRC_FILES separated by space.
Next, go to your jni folder and build the project using command ndk-build. This will place the .so file inside the android folder libs/armeabi
Finally rebuild the Android project from Android studio and run.
For detailed instructions and complete source checkout this gist

Related

Call shared library (.so) methods within Android Studios C files

I'm struggling with this for several days now. At the moment i'm just testing it with a simple C++ project (1 .h & 1 .cpp file) and a minimalistic App including the ndk helloJNI sample code (which worked perfect easily):
Target
Import existing C/C++ files (project) to Android Studio
Approach
After trying out some of the (dozens) of different possibilities, i think/thought the following steps would be the best solution for my purpose:
Create the shared library (Calculator.so) from Visual Studios 2015 "Create shared library for Android" (or something) [successful]
Create jniLibs folder in src/main/ with its subfolders (x86 the relevant one in my case)
Add the Android.mk file in src/main/jniLibs which has to be placed there (?)
Include statement: System.loadLibrary("Calculator") without "lib" and ".so" in MainActivity
The library is listed in Android Studio in its folder jniLibs as like the Android.mk. Moreover if i build the apk, the library is successfully packed (verified by unzipping) and i dont get any errors.
BUT: how can i call the methods in the library? I tried the different solutions offered in other threads, but i think i missed something in my .mk or my steps described above.
Tried
Different #include <myLib> statements in native-lib.cpp, like s
Different Android.mk settings (but i'm new to make files so not even tutorials helped me much with my specific problem ::) )
Other locations for the libCalculator.so like in the subfolder x86
and many others - simply not reminding atm (wasntme)
Your help is highly appreciated!
Android.mk
LOCAL_PATH := $(call my-dir)
APP_ABI := x86
# library info
include $(CLEAR_VARS)
LOCAL_MODULE := Calculator
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/Calculator.so
LOCAL_EXPORT_C_INCLUDES := ..../Visual Studio 2015/Projects/SO_Library/SO_Library
include $(BUILD_SHARED_LIBRARY)
There are lots of things, you can do in Android NDK. For example, Camera hardware is one of the heaviest hardware in Android OS. Detecting faces, things, giving effects and for thousands of features NDK is the best.
Some helps for your steps:
You can built and prebuilt shared(.so) and static(.a) libraries in Android Studio also. Not need Visual Studio.
Don't create jniLibs folder in main folder. When you build your project via gradle, it already creates this folder and put your target libraries. If you want prebuilt any libraries, put these libraries in main/jni/libs folder and prebuilt then with Android.mk.
Don't add the Android.mk file in jnilibs folder. Create this file in main/jni folder. Also Application.mk file.
Call your libraries, in any activity, where you need, in static method. Like this:
static { System.loadLibrary("my_library") }
Without "lib" and ".so" extensions.
When you want to call your native methods, just use "native" keyword. For example:
private native int nGetNumberFromNativeSide();
Just call this method, where you want, and get result. But for ndk building in gradle side, look at this answer. For building library in Android.mk, these sample lines maybe help you:
include $(CLEAR_VARS)
ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))
LOCAL_MODULE := my_library
LOCAL_SRC_FILES := $(LOCAL_SRC_LOCATION)/native1.cpp native2.cpp
include $(BUILD_SHARED_LIBRARY)
You can put name anything you want, but dont add lib and .so extensions. Ndk is already doing it.
I have already gave Android.mk example.
When you build Android.mk file, it locates your libraries appropriate folder. Like main/libs/x86/libmy_library.so.
I guess this answer will help you. If you have more questions, add to comment, i'll edit my answer and add answers.

NDK for beginner : where/how to add source files?

I'm trying to use the NDK, and I've been working with official samples to get started. I've managed to get the "Hello JNI" sample working :
https://github.com/googlesamples/android-ndk/tree/master/hello-jni
(I work with Android Studio)
But I don't know how to add source files to the project. So, for example, the JNI function provided is (I removed macros that aren't useful for this) :
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
Let's say I want to get the string from a C function "getString()", defined as below:
const char* getString()
{
return "Hello from getString()";
}
//Then, JNI function becomes
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, getString());
}
If I create a getString.h where I declare the function, and put the implementation in my current and only one source file, everything works like a charm. So, headers do work.
However, If I create a GetString.c file where I put the implementation, my code stops compiling. I do understand it's because GetString.o doesn't get linked (or even compiled ? I don't know), but I have no idea about how to tell Android Studio to compile both hello-jni.c (sample's source fil) and GetString.c
Should I get my hands dirty and modify gradle files ?
I also heard about a file called Android.mk which acts like a makefile, but I haven't found it in the project. If it's mandatory, should I create it, and what to put in it ? If it's not, how does the IDE knows he must build hello-jni.c ? (AKA "how did the project get configured before I modified it")
If you need any information about java-side things or gradle scripts, just have a look on the github link :)
Well, a bit of testing was enough to confirm what I thought. I just had to create Android.mk :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := hello-jni.c, GetString.cpp
LOCAL_MODULE := hello-jni
include $(BUILD_SHARED_LIBRARY)

Using opencv in native code for Android app development

I have namespace error building with ndk-build for native code in my Android app. The error sample is
C:/adt-bundle-windows-x86/ndk/sources/cxx-stl/gnu-libstdc++/4.6/include/bits
/allocator.h:54:1: error: unknown type name 'namespace'
C:/adt-bundle-windows-x86/ndk/sources/cxx-stl/gnu-libstdc++/4.6/include/bits
/allocator.h:55:1: error: expected ',' or ';' before '{' token
For OpenCV settings, my Application.mk file is
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi
APP_PLATFORM := android-10
That means I am using gnu-libstdc++ in compiling the native code.
My jni.c has c extension. That is I receive from my third party and they prefer in .c extension as if they have to change to .cpp extension, they have to change a lot in their other libraries.
So far is OK, I did all project settings for OpenCV for native development and if I do ndk-build, I can make .so libraries.
The problem of those namespace error happened when I include OpenCV's header file #include <opencv2/contrib/detection_based_tracker.hpp> into jni.c and I got a lot of name space error. If I include that #include <opencv2/contrib/detection_based_tracker.hpp> into cpp file, no error.
My questions are
(1)Is the error is because of using .hpp file in .c file?
(2)If I have no choice and have to use that .c file, is there way around to remove that error?
Thanks
My assumption would be that the file is compiled as a "C" file instead of a "C++" file because of the extension ".c". That means you cannot use any "C++" Code in your jni.c, wike classes or namespaces. These are obviously used however in your file "detection_based_tracker.hpp" that you are using.
So the problem is not that you include a file named ".hpp", but that this file contains "C++" code wich the "C" compiler cannot handle.
One solution to this problem is to only use the "C" functions in opencv (for example "opencv2/imgproc/imgproc_c.h" instead of "opencv2/imgproc/imgproc.hpp"). However, your function "detection_based_tracker.hpp" might not have a "C" version, as far as I can see.
The other option is to add a second file "function.cpp" with the "C++" functions that use opencv. The functions from "function.cpp" can be declared in a file "functions.h" and included in your "jni.c", so you can still use opencv c++ functions. Be careful to only use C style functions then, though (no classes, namespaces, ...) in your "function.h" file, otherwise you will have the same problems as before.

How to add dynamic c++ library to Android source?

I need to add my native library to Android source for others applications can use it (call functions from this library in their code). I need to use library like embed without adding it to every project in that I want use it. But i can't find information about this.
Please give me information how to do this. Sorry
As far as I understand, what you are trying to do is to run c/c++ code on Android. Am I right?
To be able to do that, you should use Android NDK to build your native library, and then load it into java code.
You need to follow 4 simple steps to run native code on android, after installing ndk:
1) Create Java "wrapper" for your native code - for. eg. create class named MyNatives which will hold method declared with native keyword. This tells the compiler, that implementation of this method is done in native library. Create static initializer, which will load the library. eg:
public class MyNatives {
static {
System.loadLibrary("hello-jni");
}
public void native nativeMethod(int x);
}
2) Compile the code, and run tool called javah for your native class (there are some plugins for eclipsee which will do that for you, eg. sequoyah)
cd <your project path>
mkdir jni
javah -d jni -classpath bin/classes com.example.MyNatives
This will generate header in jni directory (all native code in android project should be inside this direcotry)
3) Add implementation of your method from generated header
4) Create makefile for android build system and build library. Makefile should be named Android.mk. It makes use of some specific variables and macros, for more info please see NDK documentation, eg:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# your library name
LOCAL_MODULE := hello-jni
# all source files
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
to buld library just call ndk-build from project root directory
For more info, please see Android NDK documentation. Hope it helped a little.

OpenCV Android NDK Project will not build

I am using OpenCV 2.4.4 with Eclipse Juno on Ubuntu.
My problem is similar to this one OpenCV for android sample programs showing error
But is now weirding me out. I spent most of my weekend trying to get the ndk and opencv library to play nice and still I cannot get it to work. I have in my test C++ cpp file with the following includes -
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <cstdlib>
using namespace cv; //this is a problem
...
...
And it tells me when I try to build that "namespace cv cannot be found".
Oh well, I must have written some path wrong or am not using the correct library, right?
Wrong.
In the terminal, ndk-build builds the .so files without any errors. I can see them plain as day in the project folder.
But if I try to do build in eclipse, i.e. build the apk for tesitng on a virtual device or real device, then I get the namespace cv error and the build fails and then in the cpp file cv is underlined red and in eclipse the file is marked red and I can't even attempt to build until this file is "corrected".
Clearly I'm doing something wrong. But if I close my eclipse project and then reopen it, the cpp file is no longer marked red and I can make an apk build. If I attempt to open the cpp file the red returns and no more builds can happen until I go through the project close/open rigmarole.
I honestly don't know what the cause of the problem is. Any help would be greatly appreciated.
My android.mk file:
include $(CLEAR_VARS)
OPENCV_CAMERA_MODULES:=off
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=STATIC
include /the/correct/path/tp/opencv/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := mylib.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all #i have tried various targets
APP_PLATFORM := android-8
APP_MODULES := mylib
I didn't think it would be this difficult. I should add that I have successfully used opencv with Android in anothe rproject I built on WIndows with Eclipse 3.5 (I think) and OpenCV 2.4.2
EDIT
I also want to say that I just did a quick 'n dirty test opencv operation. I wrote a quick Sobel function and called it as a native function in a Java file and "sobelled" a bitmap successfully. Of course, I still had to close/open my project to do this.
Hi I had same problem with you and after I added below "opencv android sdk" path that include problem disappeared.
exp : C:\project\OpenCV-2.4.6-android-sdk\sdk\native\jni\include
switch the path with your opencv-android-sdk path.
I know that's maybe too late, but in my case (Windows+Eclipse) I correct this problem just changing the backslash "\" to slash "/" in the Path and Symbols include of opencv jni libs.
Example:
Wrong H:\opencv\sdk\native\jni\include
Correct H:/opencv/sdk/native/jni/include

Categories

Resources