How to use recompiled OpenCV build for Android - android

So I want to modify one of the files in the OpenCV build for Android and I followed the instructions on their site to download the build and I was able to make it successfully. I modified one of the files (calibinit.cpp) and made it again and copied the files in the
opencv/platforms/build_android_arm/lib/
folder into the jniLibs folder of my AndroidStudio Project.
However, the changes I made are definitely not working. I already had a previous OpenCV library linked to my project, so I'm pretty sure it's still using the old code. How do I use the new build with my AndroidStudio Project?

Can you provide more details about how u use jni in Android Studio Project?
Did u try to clean and rebuild?
Do you have your own custom Android.mk? cause Android Studio will generate its own Android.mk, which can lead to unexpected result as u thought.

delete jniLibs folder and every so file, you don't need them.
define NDK path in local.properties file:
sdk.dir=D:\Android\SDK
ndk.dir=D:\Android\NDK
create a folder(i named it jni) and put Android.mk and Application.mk in it (and an empty dummy.c file for preventing future buggy errors)
as Roy said, Android Studio generates it's own Android.mk, we have our own Android.mk file and Android Studio must use it.jni.srcDirs = []prevents that generation!
Extract openCV sources somewhere, i put them here: D:\Android\Libs\OpenCV
here is my files, modify and use them
build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "your.package"
minSdkVersion 11
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
sourceSets {
main {
jni.srcDirs = [] /*disables automatic ndk-build call */
}
}
task ndkBuild(type: Exec) {
commandLine file('D:\\Android\\NDK\\ndk-build.cmd').absoluteFile,
'NDK_PROJECT_PATH='+file('src\\main\\jni').absolutePath,
'APP_BUILD_SCRIPT='+file('src\\main\\jni\\Android.mk').absolutePath,
'NDK_APPLICATION_MK='+file('src\\main\\jni\\Application.mk').absolutePath,
'NDK_LIBS_OUT='+file('src\\main\\jniLibs').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.1.1'
compile project(':openCVLibrary300rc1')
}
Application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a x86
APP_PLATFORM := android-8
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#opencv
OPENCVROOT:= D:/Android/Libs/OpenCV
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk
//I have a local source file, you can remove it
LOCAL_SRC_FILES := DetectionBasedTracker_jni.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS += -llog
LOCAL_MODULE := detection_based_tracker
include $(BUILD_SHARED_LIBRARY)

Related

What is the equivalent of target_link_libraries in Android.mk

I am trying to compile an android project using Android.mk and need to include the following libraries: native-audio-jni android log OpenSLES.
A similar project (https://github.com/googlesamples/android-ndk/tree/master/native-audio), which includes the same libraries but uses CMakeLists.txt instead of Android.mk has this line in the CMakeLists.txt:
target_link_libraries(native-audio-jni android log OpenSLES)
This sample project builds and runs fine.
Based on findings from my online research on the topic, I have tried including the following lines in my Android.mk file, which is in the jni folder:
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lOpenSLES -lnative-audio-jni
LOCAL_LDLIBS += -landroid
ldLibs = ["android", "log", "native-audio-jni", "OpenSLES"]
LOCAL_SHARED_LIBRARIES += libandroid
LOCAL_LDLIBS := -llog
However, I still get errors like:
undefined reference to `AAssetManager_fromJava'
undefined reference to `AAssetManager_open'
undefined reference to `SL_IID_SEEK'
undefined reference to `SL_IID_MUTESOLO' ...
I also have the following includes in my .c file where the errors are generated:
// for native audio
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
// for native asset manager
#include <sys/types.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/log.h>
So my question is: How to add these libraries to my Android.mk or in other words: What is the equivalent of target_link_libraries(native-audio-jni android log OpenSLES) in Android.mk? For a number of reasons I need to use Android.mk instead of CMakeLists.txt in my project.
Here also is my build.gradle if this is of any help:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.google.ar.sceneform.samples.drawing"
// 24 is the minimum since ARCore only works with 24 and higher.
minSdkVersion 24
targetSdkVersion 27
versionCode 1
versionName "1.0"
ndk {
//ldLibs "android", "log", "native-audio-jni", "OpenSLES" // Not helping
/*
* Sceneform is available for the following ABIs: arm64-v8a, armv7a,
* x86_64 and x86. This sample app enables arm64-v8a to run on
* devices and x86 to run on the emulator. Your application should
* list the ABIs most appropriate to minimize APK size (arm64-v8a recommended).
*/
abiFilters 'arm64-v8a' ,'x86' // , 'armeabi-v7a'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
ndkBuild {
path '../jni/Android.mk'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
//implementation fileTree(dir: 'libs', include: ['*.jar']) // NOT helping
implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.7.0'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation files('Libs/YouTubeAndroidPlayerApi.jar')
implementation 'com.github.barteksc:android-pdf-viewer:2.0.3'
implementation 'com.xw.repo:bubbleseekbar:3.19-lite'
}
repositories {
mavenCentral()
}
apply plugin: 'com.google.ar.sceneform.plugin'
sceneform.asset('sampledata/models/andy.obj',
'default',
'sampledata/models/andy.sfa',
'src/main/res/raw/andy')
And my Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(CLEAR_VARS)
LOCAL_MODULE := aubio
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libaubio.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := pitch
LOCAL_SRC_FILES := pitch.c
LOCAL_SHARED_LIBRARIES := aubio
include $(BUILD_SHARED_LIBRARY)
LOCAL_LDLIBS := -llog -lOpenSLES -lnative-audio-jni -landroid
An this is a screenshot of the built error:
enter image description here
Your Android.mk got some unnecessary definitions that ruin happen to hide he correct one:
LOCAL_LDLIBS := -llog -lOpenSLES -lnative-audio-jni -landroid
instead of all the lines that you posted. NDK knows where to find these libraries, therefore -L$(SYSROOT)/… is not necessary, but only can hurt. The other lines probably come from frustration.

Android NDK: Are you sure your NDK_MODULE_PATH variable is properly defined?

recently (3 days ago) started learning Android Studio. I bought an Eclipse game project to play with, but I am getting errors. And when I fix that error, I get a new error. The current error is as following:
Build command failed. Error while executing process
C:\Users\user\AppData\Local\Android\Sdk\ndk-bundle\ndk-build.cmd with
arguments {NDK_PROJECT_PATH=null
APP_BUILD_SCRIPT=C:\APPS\app\src\main\jni\Android.mk
NDK_APPLICATION_MK=C:\APPS\app\src\main\jni\Application.mk
APP_ABI=armeabi NDK_ALL_ABIS=armeabi NDK_DEBUG=0
APP_PLATFORM=android-15
NDK_OUT=C:/APPS/app/build/intermediates/ndkBuild/release/obj
NDK_LIBS_OUT=C:\APPS\app\build\intermediates\ndkBuild\release\lib
APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n} Android
NDK: C:\APPS\app\src\main\jni\Android.mk: Cannot find module
with tag 'box2D' in import path Android NDK: Are you sure your
NDK_MODULE_PATH variable is properly defined ? Android NDK: The
following directories were searched: Android NDK:
process_begin: CreateProcess(NULL, "", ...) failed.
I have googled and I saw a few other people had asked this question on this forum, but I didn't understand how to fix it (again, I'm a complete beginner)
Here's my build.gradle (Module: app):
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.getemplate.catadventure"
minSdkVersion 15
targetSdkVersion 26
ndk {
moduleName "player_shared"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
}
dependencies {
compile 'com.google.android.gms:play-services:+'
compile files('libs/dagger-1.2.2.jar')
compile files('libs/javax.inject-1.jar')
compile files('libs/nineoldandroids-2.4.0.jar')
compile files('libs/support-v4-19.0.1.jar')
}
And here is my Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := player_shared
LOCAL_MODULE_FILENAME := libplayer
LOCAL_SRC_FILES := main.cpp
LOCAL_WHOLE_STATIC_LIBRARIES := core_static cocos2dx_static box2d_static
GOOGLE_PLAY_STORE := true
include $(BUILD_SHARED_LIBRARY)
$(call import-module, box2D)
$(call import-module, core)
$(call import-module, cocos2dx)
$(call import-module,android-ndk-profiler/jni)
Thanks in advance.

OpenCV undefined reference to `cv::fastFree(void*)'

I try to build project with OpenCV, i downloaded OpenCV SDK 3.1 from official website, however during building i get error
/Users/Mario/Downloads/OpenCV-android-sdk/sdk/native/jni/include/opencv2/core/mat.inl.hpp
Error:(571) undefined reference to 'cv::fastFree(void*)'
Error:(663) undefined reference to 'cv::Mat::create(int, int const*, int)'
Error:(682) undefined reference to 'cv::Mat::deallocate()'
here is my gradle.build, i use gradle-experimental:0.4.0
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "pl.mariusz.opencv"
minSdkVersion.apiLevel = 17
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
task ndkBuild(type: Exec) {
commandLine '/Users/Mario/Library/Android/android-ndk-r10e/ndk-build', '-C', file('src/main').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
}
android.ndk {
moduleName = "source_file"
cppFlags.add("-std=c++11")
cppFlags.add("-fexceptions")
cppFlags.add("-I${file("/Users/Mario/Downloads/OpenCV-android-sdk/sdk/native/jni/include")}".toString())
cppFlags.add("-I${file("/Users/Mario/Downloads/OpenCV-android-sdk/sdk/native/jni/include/opencv")}".toString())
stl = "gnustl_static"//"gnustl_static"//"gnustl_shared"//"stlport_static"
}
android.sources {
main {
jni{
source{
srcDirs = []
}
}
jniLibs {
source {
srcDirs = ['src/main/Libs']
}
}
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
}
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCVROOT:= /Users/Mario/Downloads/OpenCV-android-sdk
OPENCV_LIB_TYPE=STATIC
include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk
LOCAL_SRC_FILES := source_file.cpp
LOCAL_LDLIBS += -llog -ldl
LOCAL_MODULE := source_file
include $(BUILD_SHARED_LIBRARY)
and Application.mk
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_PLATFORM := android-17
i tried mix it with shared,static STL with still same error, how can i fix it?
[EDIT]
[SOLUTION]
its more like compromise not real solution, but i changed gradle-experimental:0.4.0 back to classpath 'com.android.tools.build:gradle:1.5.0' and added file gradle.properties to project root directory with
android.useDeprecatedNdk=true
You have to add opencv libraries to your linker. To do that, you have to do 2 things: 1. add the library files; 2. add the library directory.
Try
LOCAL_LDLIBS += -llog -ldl -LlibPath -lopencv_calib3d -lopencv_core
and so an, add all the opencv libraries (or at least the ones you'll need) in this way. -l will automatically assume the "lib" in the filename and the suffix.
The -L will tell the linker where to find libraries, so instead of libPath please add the absolute path of your opencv library folder. See how to mention path of libraries in Android.mk file or Application.mk file?
Try it and tell me the new error message.

Android NDK Exception failed: dlopen failed: cannot locate symbol "_ZN7Tangram11setPositionEdd" referenced by "libtangram.so"

I am trying to run a demo application of a Library in which android ndk is integrated. I have imported this code in Android studio and also downloaded ndk and linked it with project. Code compiles and build succesfully. It gives crash with exception "exception ljava lang unsatisfiedlinkerror thrown while initializing" "failed: dlopen failed: cannot locate symbol "_ZN7Tangram11setPositionEdd" referenced by "libtangram.so"..."
Application.mk:
APP_STL := c++_shared
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a x86 mips
APP_PLATFORM := android-19
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tangram
LOCAL_SRC_FILES := jniExports.cpp jniGenerated.cpp platform_android.cpp
LOCAL_LDLIBS := -llog
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
include $(BUILD_SHARED_LIBRARY)
Module Gradle File:
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'com.github.dcendents:android-maven-plugin:1.2'
}
}
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
group = GROUP
version = VERSION_NAME
android {
compileSdkVersion 22
buildToolsVersion "21.1.2"
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
}
sourceSets.main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
jni.srcDirs = []
assets.srcDirs = ['core/resources']
}
task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
commandLine "C:/Users/Administrator/AppData/Local/Android/android-ndk-r10e/ndk-build.cmd",
'NDK_PROJECT_PATH=build/intermediates/ndk',
'NDK_LIBS_OUT=jniLibs',
'APP_BUILD_SCRIPT=jni/Android.mk',
'NDK_APPLICATION_MK=jni/Application.mk'
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
}
// Add gdb server to apk
afterEvaluate {
Sync packageTask = project.getTasks().findByName("packageReleaseJniLibs")
if (packageTask) { packageTask.include(['**/gdbserver', '**/gdb.setup']) }
packageTask = project.getTasks().findByName("packageDebugJniLibs")
if (packageTask) { packageTask.include(['**/gdbserver', '**/gdb.setup']) }
}
dependencies {
compile 'com.squareup.okhttp:okhttp:2.5.0'
compile 'xmlpull:xmlpull:1.1.3.1'
}
apply from: file('gradle-mvn-push.gradle')
In Java class load libraries:
static {
System.loadLibrary("c++_shared");
System.loadLibrary("tangram");
}
I google this issue and in these posts Link1 Link2 Link3 Link4 it is mentioned that it may be the issue of compiling at api 21 or newer and running it on older devices. But i have mentioend APP_PLATFORM := android-19 in my Application.mk and getting this exception.
Any Help?
It looks like you tried to compile the tangram project from your own custom ndk-build as opposed to their recommended build process (https://github.com/tangrams/tangram-es#android). Use their build process with make to create the libtangram.so file, and then copy that .so file into your native libraries directory for your app.
The reason it can't find those symbols is because you aren't including the appropriate source files that define those functions when building with the ndk. By ingnoring undefined symbols, it will compile but won't be able to resolve them at runtime.
The symbol you are missing is created from Tangram::setPosition(double, double) which is defined at https://github.com/tangrams/tangram-es/blob/master/core/src/tangram.cpp#L318 ; however, your Android.mk file doesn't include that source file.

NDK-build vs Android Studio NDK Build

To run some Native code you can execute ndk-build command but I am confused if the Eclipse or Android Studio IDEs execute this command automatically on the Compile-time or how ndk-build command is related to the mentioned IDEs when I compile my code by eclipse or droid studio?
For eclipse, there are already too many online sources related to it, so I will talk about Android Studio here.
If you don't have your onw native files (C++,C) in your project, just put the .a or .so native libraries in the src/main/jniLibs folders and you don't have to modify anything in the gradle file. The system will do everything for you automatically.
If you have your own native files and have put them in the src/main/jni folder, then you have to create your own makefiles and put them in the jni folder as well. You also have to modify the gradle file in your app module.
Here is what I did for a face detection sample of opencv, and I got the original code from this wonderful post(Here), which was actually modified from another one's method for simpler execution. The philosophy is rather simple: compile the native source codes and put the generated .so/.a library into the jniLibs folder:
My project structure:
Project Structure
My makefiles (make sure you have the original sdk of the library for reference in the makefile):
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include /home/ng/Desktop/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL_SRC_FILES := DetectionBasedTracker_jni.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS += -llog -ldl
LOCAL_MODULE := detection_based_tracker
include $(BUILD_SHARED_LIBRARY)
Application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a armeabi
APP_PLATFORM := android-19
My gradle.build file in the app module:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
applicationId "org.opencv.samples.facedetect"
minSdkVersion 14
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
sourceSets.main.jni.srcDirs = []
task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
// ndkDir = project.plugins.findPlugin('com.android.application').getNdkFolder()
commandLine "$ndkDir/ndk-build",
'NDK_PROJECT_PATH=build/intermediates/ndk',
'NDK_LIBS_OUT=src/main/jniLibs',
'APP_BUILD_SCRIPT=src/main/jni/Android.mk',
'NDK_APPLICATION_MK=src/main/jni/Application.mk'
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.0'
compile project(':openCVLibrary300')
}
You don't actually have to change other gradle files for compiling the native part of the project.
You could also compile the native sources codes by command line and put the .so files back to the jniLibs folder. This also works.
I hope this could help in your problem.
If you want you could compile it using Terminal commands or else you could configure both the IDEs to do automatically
Today Android-Studio (Canary) Preview 1.3 RC1 got released with jni/ndk support out of the box. No need to call commandline tools anymore.
https://sites.google.com/a/android.com/tools/download/studio/canary/latest
Release Notes:
https://sites.google.com/a/android.com/tools/recent/androidstudiowithandroidndkpreviewsupportavailable

Categories

Resources