Ask Your Question
0

Problem adding function to OpenCV4Android: UnsatisfiedLinkError

asked 2015-02-27 06:22:40 -0600

SARGE553413 gravatar image

updated 2015-03-03 08:04:56 -0600

I have to add a function to OpenCV4Android library (it will be a copy of an existing function, but modifed). For now, I'm trying to add a very simple function for testing, its only objective is to return an integer value. I have compiled the library with no errors, but when I try to call this function from java, I have an error: UnsatisfiedLinkError. I don't know what I'm doing wrong. I'm working on windows.

What I have tested:

In file ${opencv_folder}\modules\java\generator\src\cpp\utils.cpp Add at the end of file the following:

extern "C"{
[...]

/*
 * Class:     org_opencv_android_Utils
 * Method:    int test()
 */

JNIEXPORT jint JNICALL Java_org_opencv_android_Utils_test
    (JNIEnv * env, jclass);

JNIEXPORT jint JNICALL Java_org_opencv_android_Utils_test
    (JNIEnv * env, jclass)
{
    return (jint) 24;
}   

} //extern "C"

In file ${opencv_folder}\modules\java\generator\src\java\android+Utils.java add at the end of file the following:

public static int test22(){
    return test();   //Here the UnsatisfiedLinkError
}

private static native int test();

Finally, in my java project:

import org.opencv.android.Utils;
[...]
void test_opencv4android(){
     int n = Utils.test22();  
}

I have no errors in eclipse, it detects the function in the module.

What I do to compile:

cd ${opencv_folder}\platforms\build_android_arm
cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=..\android\android.toolchain.cmake ..\..
make

What's my error?

EDIT:

I have tested anotherthing, generate jni signatura via javah command, this is what I've test:

Open command line in ${opencv_folder}\platforms\build_android_arm\bin\classes, with android_build_arm the folder where I'm copilingo OpenCV4Android.

Then executing the following command:

javah -jni -classpath "${opencv_folder}\platforms\build_android_arm\bin\classes" org.opencv.android.Utils

But I have this error:

Error: Class android.content.Context could not be found.

I think it's because android.content.Context is an android library that is not in the OpenCV4Android library. How can I say to javah that have to look for that class in other folder?

EDIT2:

I have used ndk's objdump to see the real name of the function in the .so file. This is what I've found:

[...]
000986d0 <Java_org_opencv_android_Utils_test>:
   986d0:   2018        movs    r0, #24
   986d2:   4770        bx  lr
[...]

It's the expected name.

The command that I have exectued: First I have gone to

${ndk_folder}\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\arm-linux-androideabi\bin

There, I have exectued

objdump -d ${opencv_folder}\platforms\build_android_arm\lib\armeabi-v7a\libopencv_java.so > pr.txt

And then open "pr.txt" and search for Java_org_opencv_android_test.

EDIT 3:

I think the problem may be that the .so file libopencv_java.so, which is called by java, that I'm seeing in my pc and I have changed and compiled, is not in my android device.

I think this may be due to you have to download OpenCV manager in android to execute any application that uses OpenCV, an this manager has its own .so files.

Then, how can I replace libopencv_java.so on my device with the library that I have in my computer?

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2015-03-03 16:21:43 -0600

SARGE553413 gravatar image

updated 2015-03-03 16:23:41 -0600

I have solved the problem.

As I thought, the problem was that, despite I compiled well the modified OpenCV4Android library, I was loading the library dinamically, these changes were not applied, then I was using the library that comes with OpenCV manager (for android).

The solution is make the load to be static, this is, copy ${OpenCV4Android_folder}\lib\<target_arch> to ${proyect_folder}\libs.

Then make the library loading statically. Here an example:

private BaseLoaderCallback mOpenCVCallBack;

[...]

mOpenCVCallBack = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
        case LoaderCallbackInterface.SUCCESS:
            //Hacer cosas si se ha cargado bien?
            break;
        default:
            super.onManagerConnected(status);
            break;
        }
    }
};

if (!OpenCVLoader.initDebug()){
    //Handle error 
}else{
    mOpenCVCallBack.onManagerConnected(LoaderCallbackInterface.SUCCESS); 
}

NOTE: This solutions is only valid for proyects that not use JNI, otherwise you must follow this tutorial: http://docs.opencv.org/trunk/doc/tuto...

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2015-02-27 06:22:40 -0600

Seen: 896 times

Last updated: Mar 03 '15