I have a C++ (ImageExtraction.cpp) file which uses OpenCV. Here is the snapshot of C++ file. I want to call this native C++ file from my Android java file. I am using Mac...
#include < string.h>
#include < jni.h>
#include < opencv2/imgproc/imgproc.hpp>
#include < opencv2/highgui/highgui.hpp>
#include < iostream>
#include < cv.h>
#include < stdio.h>
#include < algorithm>
#include < functional>
using namespace cv;
using namespace std;
extern "C"
{
JNIEXPORT jint JNICALL Java_com_clematistech_businesscardreader_BusinessCardReader_stringFromJNI(JNIEnv *env, jobject obj)
{
........
}
}
Here is my Android.mk:
LOCAL_PATH := $(call my-dir)
LOCAL_C_INCLUDES := /usr/local/include/opencv
include $(CLEAR_VARS)
include /Users/sritomamajumder/Documents/MISC/Softwares/OpenCV_for_Android/OpenCV-2.4.10-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL_LDLIBS := -llog
LOCAL_MODULE := ImageExtraction
LOCAL_SRC_FILES := ImageExtraction.cpp
LOCAL_STATIC_LIBRARIES := libzip libpng libjpeg freetype
LOCAL_STATIC_LIBRARIES += libopencv_contrib libopencv_legacy libopencv_ml libopencv_stitching libopencv_nonfree libopencv_objdetect libopencv_videostab libopencv_calib3d libopencv_photo libopencv_video libopencv_features2d libopencv_highgui libopencv_androidcamera libopencv_flann libopencv_imgproc libopencv_ts libopencv_core
include $(BUILD_SHARED_LIBRARY)
Here is the Application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all
APP_PLATFORM := android-10
APP_MODULES := ImageExtraction
When I ran ndk-build command from my root Android project I am getting the following errors:
[arm64-v8a] Compile++ : ImageExtraction <= ImageExtraction.cpp
[arm64-v8a] SharedLibrary : libImageExtraction.so
./obj/local/arm64-v8a/objs/ImageExtraction/ImageExtraction.o: In function `cv::Mat::~Mat()':
/Users/sritomamajumder/Documents/MISC/Softwares/OpenCV_for_Android/OpenCV-2.4.10-android-sdk/sdk/native/jni/include/opencv2/core/mat.hpp:278: undefined reference to `cv::fastFree(void*)'
......
Please let me know what I have done wrong.
with APP_ABI set to all, the latest NDKs is set to compile your code for all 64bit platforms (arm64-v8a, x86_64...) as well as the 32bit ones.
But your OpenCV package doesn't contain binaries for 64bit platforms, I guess that's why you're experiencing the current issue.
You can set APP_ABI to all32 inside your Application.mk file to target only 32bit platforms (armeabi-v7a x86 armeabi mips) for which the OpenCV package is providing prebuilts for.
Related
I need your help because it drives me crazy. What cause my error?
The error is
"jni/algorithm.cpp:4:33: fatal error: opencv2/core/core.hpp: No such file or directory #include <opencv2/core/core.hpp>
^ compilation terminated. make: *** [obj/local/arm64-v8a/objs/algorithm/algorithm.o] Error 1"
My algorithm.cpp is:
#include <jni.h>
#include <string.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc_c.h"
using namespace std;
using namespace cv;
extern "C"
{
JNIEXPORT jlong JNICALL Java_com_example_hematoma_MainActivity_fce(JNIEnv *env, jobject obj, jlong matimage)
{
Mat *jni_image = (Mat*) matimage;
return (jlong)jni_image;
}
}
My Android.mk is:
LOCAL_PATH := $(call my-dir)
include /home/nemesis/adt-bundle-linux-x86_64-20140702/OpenCV-2.4.10-android-sdk/sdk/native/jni/OpenCV.mk
include $(CLEAR_VARS)
LOCAL_MODULE := algorithm
LOCAL_SRC_FILES := algorithm.cpp
LOCAL_C_INCLUDE := /home/nemesis/adt-bundle-linux-x86_64-20140702/OpenCV-2.4.10-android-sdk/sdk/native/jni/include/opencv2/core/core.hpp
LOCAL_C_INCLUDE += /home/nemesis/adt-bundle-linux-x86_64-20140702/OpenCV-2.4.10-android-sdk/sdk/native/jni/include/
include $(BUILD_SHARED_LIBRARY)
The error occurs when ndk try to build .so
Thanks in advance.
LOCAL_C_INCLUDE := /home/nemesis/adt-bundle-linux-x86_64-20140702/OpenCV-2.4.10-android-sdk/sdk/native/jni/include/opencv2
should be
LOCAL_C_INCLUDES := /home/nemesis/adt-bundle-linux-x86_64-20140702/OpenCV-2.4.10-android-sdk/sdk/native/jni/include
ie, it is plural and should point to the location from which the following is a relative path:
#include <opencv2/core/core.hpp>
I solved my problem by add LOCAL_LDLIBS += -llog -ldl to "Android.mk"
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include C:/.../OpenCV-3.1.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := Testappcv
LOCAL_SRC_FILES := Testappcv.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
And added "Application.mk" file to jni folder
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_PLATFORM := android-8
So, I tried to change in Project properties C/C++ Build -> Build command from ${NDKROOT}/ndk-build to ${NDKROOT}/ndk-build.cmd and it solved all my include libs errors. weird
I am trying my hand at Android JNI.
So far I have just written the basic Hello World Android JNI App.
Now I was thinking if it would be possible to build a .so file seperately. Then use that library in my JNI Layer C Code.
So basically I want to build a libsample.so using command line gcc in windows. Then use this .so file in the JNI I write for my android app.
So far from my understanding I should be able to do this by editing the Android.mk file.
But what would those edits be ?
EDIT: Source code attached.
jnitest.cpp -
#include <jni.h>
#include "specialPrint.h"
extern "C" jstring Java_com_example_hwjni_MainActivity_helloFromJni(JNIEnv *env, jobject thiz) {
return env->NewStringUTF(SpecialPrint("This is external .so talking."));
}
specialPrint.h -
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
char* SpecialPrint(char* s);
#ifdef __cplusplus
}
#endif
specialPrint.c -
#include <stdio.h>
#include "specialPrint.h"
char* SpecialPrint(char* s) {
return s;
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyPrebuiltLib
LOCAL_SRC_FILES = specialPrint.c
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := jnitest
LOCAL_SRC_FILES := jnitest.cpp
LOCAL_SHARED_LIBRARIES := MyPrebuiltLib
include $(BUILD_SHARED_LIBRARY)
P.S. - Although right now I am trying to do this with the source. But eventually I really need to do this stuff without the source of specialPrint. If you could help me achive that then it would be great!
Step 1: declare a prebuilt library as module
Step 2: refer the prebuilt module as local shared library
for example
include $(CLEAR_VARS)
LOCAL_MODULE := MyPrebuiltLib
LOCAL_SRC_FILES = path/to/libSuper.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := DroidJNILib
LOCAL_SRC_FILES := AwsomeCode.cpp
LOCAL_SHARED_LIBRARIES := MyPrebuiltLib
include $(BUILD_SHARED_LIBRARY)
If you have the source
include $(CLEAR_VARS)
LOCAL_MODULE := MyPrebuiltLib
LOCAL_SRC_FILES =mysource.cpp
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := DroidJNILib
LOCAL_SRC_FILES := AwsomeCode.cpp
LOCAL_SHARED_LIBRARIES := MyPrebuiltLib
include $(BUILD_SHARED_LIBRARY)
I am trying to import the TagLib C++ library (http://taglib.github.io/) to Android using the NDK.
I was able to successfully compile the library by putting all the source code under /jni/taglibroot/ as per picture bellow:
and running ndk-build on the /jni folder.
However, I have also created the tag_lib_personal.cpp file bellow (to use the TagLib API):
#include <jni.h>
/*#include <iostream>
#include <iomanip>*/
#include <stdio.h>
#include <taglibroot/taglib/fileref.h>
#include <taglibroot/taglib/tag.h>
#include <taglibroot/taglib/tpropertymap.h>
#ifdef __cplusplus
extern "C"
{
#endif
jstring Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
TagLib::FileRef f(argv[i]);
if(!f.isNull() && f.audioProperties()) {
TagLib::AudioProperties *properties = f.audioProperties();
int seconds = properties->length() % 60;
int minutes = (properties->length() - seconds) / 60;
/*cout << "-- AUDIO --" << endl;
cout << "bitrate - " << properties->bitrate() << endl;
cout << "sample rate - " << properties->sampleRate() << endl;
cout << "channels - " << properties->channels() << endl;
cout << "length - " << minutes << ":" << formatSeconds(seconds) << endl;*/
}
return "hello world!";
//return (*env)->NewStringUTF(env, "Hello from native code!");
}
#ifdef __cplusplus
}
#endif
But I cannot get it to compile. When I try to run ndk-build again I get the following error:
[armeabi] Compile++ arm : my_own_source_files <= tag_lib_personal.cpp
In file included from D:/blabla/eclipse-jee-indigo-SR2-win32-x86_64/workspace/Project//jni/tag_lib_personal.cpp:7:0:
D:/blabla/eclipse-jee-indigo-SR2-win32-x86_64/workspace/Project//jni/taglibroot/taglib/fileref.h:29:19: fatal error: tfile.h: No such file or directory
compilation terminated.
make.exe: *** [D:/blabla/eclipse-jee-indigo-SR2-win32-x86_64/workspace/Project//obj/local/armeabi/objs/my_own_source_files/tag_lib_personal.o] Error 1
The error shows it cannot find some .h files from the TagLib library. Here is my Android.mk file though:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := taglib_module
FILE_LIST := $(wildcard $(LOCAL_PATH)/taglibroot/*.cpp) #Based on: http://stackoverflow.com/a/8980441
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/foo
LOCAL_EXPORT_CFLAGS := -DFOO=1
LOCAL_EXPORT_LDLIBS := -llog
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
# If I run ndk-build only on the above code, it compiles the TagLib library successfully and generates the .so files as expected
include $(CLEAR_VARS)
LOCAL_MODULE := my_own_source_files
LOCAL_SHARED_LIBRARIES := taglib_module
LOCAL_SRC_FILES := tag_lib_personal.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/taglibroot/taglib,\
$(LOCAL_PATH)/taglibroot/taglib/ape,\
$(LOCAL_PATH)/taglibroot/taglib/asf,\
$(LOCAL_PATH)/taglibroot/taglib/flac,\
$(LOCAL_PATH)/taglibroot/taglib/it,\
$(LOCAL_PATH)/taglibroot/taglib/mod,\
$(LOCAL_PATH)/taglibroot/taglib/mp4,\
$(LOCAL_PATH)/taglibroot/taglib/mpc,\
$(LOCAL_PATH)/taglibroot/taglib/mpeg,\
$(LOCAL_PATH)/taglibroot/taglib/mpeg/id3v1,\
$(LOCAL_PATH)/taglibroot/taglib/mpeg/id3v2,\
$(LOCAL_PATH)/taglibroot/taglib/mpeg/id3v2/frames,\
$(LOCAL_PATH)/taglibroot/taglib/ogg,\
$(LOCAL_PATH)/taglibroot/taglib/ogg/flac,\
$(LOCAL_PATH)/taglibroot/taglib/ogg/opus,\
$(LOCAL_PATH)/taglibroot/taglib/ogg/speex,\
$(LOCAL_PATH)/taglibroot/taglib/ogg/vorbis,\
$(LOCAL_PATH)/taglibroot/taglib/riff,\
$(LOCAL_PATH)/taglibroot/taglib/riff/aiff,\
$(LOCAL_PATH)/taglibroot/taglib/riff/wav,\
$(LOCAL_PATH)/taglibroot/taglib/s3m,\
$(LOCAL_PATH)/taglibroot/taglib/toolkit,\
$(LOCAL_PATH)/taglibroot/taglib/trueaudio,\
$(LOCAL_PATH)/taglibroot/taglib/wavpack,\
$(LOCAL_PATH)/taglibroot/taglib/xm
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
As you can see I put every single directory of the TagLib library that has at least one .h file in the LOCAL_EXPORT_C_INCLUDES directive but it for some reason still cannot find tfile.h (which is inside $(LOCAL_PATH)/taglibroot/taglib/toolkit). What am I missing?
You are not missing, you have an extra ;-)
Syntax for LOCAL_C_INCLUDES does not expect these commas. You simply list all directories. Actually, you can use LOCAL_EXPORT_C_INCLUDES instead (your post hints that you probably tried):
LOCAL_C_INCLUDES := $(LOCAL_PATH)/taglibroot/taglib\
$(LOCAL_PATH)/taglibroot/taglib/ape\
$(LOCAL_PATH)/taglibroot/taglib/asf\
$(LOCAL_PATH)/taglibroot/taglib/flac\
$(LOCAL_PATH)/taglibroot/taglib/it\
$(LOCAL_PATH)/taglibroot/taglib/mod\
$(LOCAL_PATH)/taglibroot/taglib/mp4\
$(LOCAL_PATH)/taglibroot/taglib/mpc\
$(LOCAL_PATH)/taglibroot/taglib/mpeg\
$(LOCAL_PATH)/taglibroot/taglib/mpeg/id3v1\
$(LOCAL_PATH)/taglibroot/taglib/mpeg/id3v2\
$(LOCAL_PATH)/taglibroot/taglib/mpeg/id3v2/frames\
$(LOCAL_PATH)/taglibroot/taglib/ogg\
$(LOCAL_PATH)/taglibroot/taglib/ogg/flac\
$(LOCAL_PATH)/taglibroot/taglib/ogg/opus\
$(LOCAL_PATH)/taglibroot/taglib/ogg/speex\
$(LOCAL_PATH)/taglibroot/taglib/ogg/vorbis\
$(LOCAL_PATH)/taglibroot/taglib/riff\
$(LOCAL_PATH)/taglibroot/taglib/riff/aiff\
$(LOCAL_PATH)/taglibroot/taglib/riff/wav\
$(LOCAL_PATH)/taglibroot/taglib/s3m\
$(LOCAL_PATH)/taglibroot/taglib/toolkit\
$(LOCAL_PATH)/taglibroot/taglib/trueaudio\
$(LOCAL_PATH)/taglibroot/taglib/wavpack\
$(LOCAL_PATH)/taglibroot/taglib/xm
Note If you encounter strange issues with ndk-build in the future, first advice is to run ndk-build V=1: it will log all actual compilation commands used by ndk-build, which may often expose the errors or typos in various Android.mk files.
PS Your build will finally fail. When you build taglib, you need also to compile all .cpp files in taglibroot subdirectories! I suggest that you try to build the library the way it was designed to be built, with CMake. The Android patches can be found here: https://code.google.com/p/android-cmake.
You can also try a straightforward approach, but I am not sure it will work:
MY_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := taglib_module
LOCAL_PATH := $(MY_PATH)/taglibroot/taglib
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)\
$(LOCAL_PATH)/ape\
$(LOCAL_PATH)/asf\
$(LOCAL_PATH)/flac\
$(LOCAL_PATH)/it\
$(LOCAL_PATH)/mod\
$(LOCAL_PATH)/mp4\
$(LOCAL_PATH)/mpc\
$(LOCAL_PATH)/mpeg\
$(LOCAL_PATH)/mpeg/id3v1\
$(LOCAL_PATH)/mpeg/id3v2\
$(LOCAL_PATH)/mpeg/id3v2/frames\
$(LOCAL_PATH)/ogg\
$(LOCAL_PATH)/ogg/flac\
$(LOCAL_PATH)/ogg/opus\
$(LOCAL_PATH)/ogg/speex\
$(LOCAL_PATH)/ogg/vorbis\
$(LOCAL_PATH)/riff\
$(LOCAL_PATH)/riff/aiff\
$(LOCAL_PATH)/riff/wav\
$(LOCAL_PATH)/s3m\
$(LOCAL_PATH)/toolkit\
$(LOCAL_PATH)/trueaudio\
$(LOCAL_PATH)/wavpack\
$(LOCAL_PATH)/xm
FILE_LIST := $(foreach dir, $(LOCAL_EXPORT_C_INCLUDES), $(wildcard $(dir)/*.cpp))
LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_EXPORT_CFLAGS := -DFOO=1
LOCAL_EXPORT_LDLIBS := -llog
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_PATH)
LOCAL_MODULE := my_own_shared_lib
LOCAL_SHARED_LIBRARIES := taglib_module
LOCAL_SRC_FILES := tag_lib_personal.cpp
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
Please note that in your Java, you will load the two libraries, and order is important:
Runtime.loadLibrary("taglib_module");
Runtime.loadLibrary("my_own_shared_lib");
I'm a newbie of Android NDK. I want to try create fast blur effect to bitmap and I found a NDK solution from here: Fast Bitmap Blur For Android SDK answered by #zeh
after I did my configuration, I am not able to run the project and It said "Type 'AndroidBitmapInfo' could not be resolved" in the *.c file.
Could you guys tell me how to fix this problem?
Here is my Android.mk
LOCAL_PATH := $(call my-dir)
# Create BitmapUtils library
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog -ljnigraphics -landroid
LOCAL_MODULE := bitmaputils
LOCAL_SRC_FILES := bitmaputils.c
LOCAL_CFLAGS = -ffast-math -O3 -funroll-loops
include $(BUILD_SHARED_LIBRARY)
Thank you
Just in case: have you correctly included the bitmap header?
#include <android/bitmap.h>
Add the following line to your Application.mk
APP_PLATFORM := android-8
In case you don't use Application.mk, run ndk-build as follows:
ndk-build APP_PLATFORM=android-8
according to ndk samples\bitmap-plasma\jni, you'd better double check mk file, and header file.
Application.mk
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-8
----------------------------------------------------------------
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := plasma
LOCAL_SRC_FILES := plasma.c
LOCAL_LDLIBS := -lm -llog -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------
plasma.c
#include <jni.h>
#include <time.h>
#include <android/log.h>
#include <android/bitmap.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
The configuration of CDT indexer needs to enable "Index unused headers ..."
To get there: Project->Properties->C/C++ General->Indexer.
Than rebuild the project
If still this appears than repeat this again.It will be gone :)
Asio (without Boost) is supposed to be usable with just the headers only right?
By default, Asio is a header-only library. (http://think-async.com)
I understand that internally Asio still depends on Boost.
This is my setup.
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := gatelib
LOCAL_SRC_FILES := gatelib.cpp
LOCAL_C_INCLUDES += /cygdrive/l/asio-1.5.3/include
LOCAL_C_INCLUDES += /cygdrive/l/boost/boost_1_49_0
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_STL := stlport_static
APP_CFLAGS += -DBOOST_DATE_TIME_NO_LIB -DBOOST_REGEX_NO_LIB
gatelib.cpp
#include <jni.h>
#include <asio.hpp>
#ifdef __cplusplus
extern "C"
{
#endif
// rest of code ...
#ifdef __cplusplus
}
#endif
Build script
#echo on
#set BASHPATH="L:\cygwin\bin\bash"
#set PROJECTDIR="/cygdrive/l/AsioAndroid/AsioDemo"
#set NDKDIR="/cygdrive/l/android-ndk-r8c/ndk-build"
%BASHPATH% --login -c "cd %PROJECTDIR% && %NDKDIR%
#pause:
Output
http://pastebin.com/XiJjvNmp
So basically, what I am trying to achieve is, get Asio working on Android (via NDK). Yes, just Asio itself, not the Asio included with Boost. The problems are presented in the output. I have no clue at all..
PS. There's no Asio tag, so I guess Boost-Asio tag will have to do for now.
Here's what I did.
Application.mk
APP_STL := gnustl_static
APP_CFLAGS += -DBOOST_DATE_TIME_NO_LIB -DBOOST_REGEX_NO_LIB
APP_CPPFLAGS += -fexceptions
The clues and hints were all over Stack Overflow. Once pieced together, it worked!