17

A few days ago I asked about an UnsatisfiedLinkError from running non-native OpenCV code. I thought the problem was solved after reinstalling Eclipse and closing/reopening all the packages, but it's back again after I put the OpenCV code into the existing onCreate() method.

I created a new Android application with an activity called Start. I then went to project properties and added OpenCV as a library. Here's the code for the activity (Start.java):

package com.test;

import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;

public class Start extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_start);

        Mat Image = Highgui.imread("/image.jpg");
        if (Image == null) {
            AlertDialog ad = new AlertDialog.Builder(this).create(); 
            ad.setMessage("Fatal error: can't open /image.jpg!");  
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_start, menu);
        return true;
    }
}

And here's the log:

08-13 12:26:14.791: E/Trace(1067): error opening trace file: No such file or directory (2)
08-13 12:26:15.191: W/dalvikvm(1067): No implementation found for native Lorg/opencv/highgui/Highgui;.imread_1:(Ljava/lang/String;)J
08-13 12:26:15.191: D/AndroidRuntime(1067): Shutting down VM
08-13 12:26:15.191: W/dalvikvm(1067): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
08-13 12:26:15.201: E/AndroidRuntime(1067): FATAL EXCEPTION: main
08-13 12:26:15.201: E/AndroidRuntime(1067): java.lang.UnsatisfiedLinkError: Native method not found: org.opencv.highgui.Highgui.imread_1:(Ljava/lang/String;)J
08-13 12:26:15.201: E/AndroidRuntime(1067):     at org.opencv.highgui.Highgui.imread_1(Native Method)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at org.opencv.highgui.Highgui.imread(Highgui.java:324)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at com.test.Start.onCreate(Start.java:18)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.Activity.performCreate(Activity.java:5008)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.access$600(ActivityThread.java:130)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.os.Looper.loop(Looper.java:137)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.main(ActivityThread.java:4745)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at java.lang.reflect.Method.invokeNative(Native Method)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at java.lang.reflect.Method.invoke(Method.java:511)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at dalvik.system.NativeStart.main(Native Method)

Again, this is non-native code, so having an Unsatisfied Link Error doesn't make much sense.

Community
  • 1
  • 1
1''
  • 26,823
  • 32
  • 143
  • 200
  • 2
    But this is java wrapper, so it calls native (c++) functions from Java code. Make sure that your apk contains `opencv_java.so`. – ArtemStorozhuk Aug 13 '12 at 17:34
  • 1
    You could ask the question here also : http://answers.opencv.org/questions/ official openCV wiki, modeled on stackoverflow it seems. – Iain_b Aug 13 '12 at 17:40
  • @Astor I realized that although the directory structure was intact, version control had dropped the actual libraries, so I had to replace them. Good call! Unfortunately, I'm still getting the same error. I have three versions of libopencv_java.so inside \OpenCV\sdk\native\libs\: one in \armeabi, one in armeabi-v7a, and one in \x86. – 1'' Aug 13 '12 at 17:53
  • @lain_b Good idea, I'll ask there too. – 1'' Aug 13 '12 at 17:55

8 Answers8

38

After a bunch of searching, I found this:

"3. If your application project doesn’t have a JNI part, just copy the corresponding OpenCV native libs from /sdk/native/libs/ to your project directory to folder libs/."

So that means copy the \armeabi, \armeabi-v7a, and \x86 folders.

"4. The last step of enabling OpenCV in your application is Java initialization code before call to OpenCV API. It can be done, for example, in the static section of the Activity class, which gets executed only once, before any instance of the class is created:

static {
    if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
    }
}

Alternatively, you can put it inside the onCreate method:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_load_image);
    if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
    }
    [...]
}

Now it works!

1''
  • 26,823
  • 32
  • 143
  • 200
  • 1
    static block shows error when created inside onCreate. It says add "EnumBody" to complete the block..what does it mean? and I am still getting the unsatisfiedLinkError.. – Rekha Aug 31 '12 at 09:26
  • 2
    The static part did the job for me. Of course it should be put out of the methods and in the main activity itself. – Mahm00d Nov 22 '13 at 15:38
  • @1" I tried the same which you covered above . I am getting exception when I execute my program. `java.lang.UnsatisfiedLinkError: Native method not found: org.opencv.highgui.Highgui.imread_1:(Ljava/lang/String;)J` – Ajay S Mar 16 '14 at 08:53
  • @TGMCians Are you sure you have `libopencv_highgui.a` under `\libs\armeabi-v7a`? And does `OpenCVLoader.initDebug()` succeed? – 1'' Mar 16 '14 at 15:55
  • It worked, I copied the *.so files at wrong location in Android Studio, thanks – Ajay S Mar 16 '14 at 16:03
  • Thanks a lot Mr. 1". I have been dealing with this issue since 4 hours and finally I landed here and as you said, copied all the .so files in the project and now its working fine. – Manpreet Nov 09 '14 at 09:12
8

you should use

if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack))
{
    Log.e("TEST", "Cannot connect to OpenCV Manager");
}

in OnCreate() And use

private BaseLoaderCallback  mOpenCVCallBack = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                               Mat Image = Highgui.imread("/image.jpg");
                               if (Image == null) {
                                   AlertDialog ad = new AlertDialog.Builder(this).create(); 
                                   ad.setMessage("Fatal error: can't open /image.jpg!");  
                                }
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
    }
    };
sdyy
  • 81
  • 3
  • This gave me many unsatisfied link exceptions when declaring members of a type from opencv. The static initialisation helped. – Bachi Sep 11 '15 at 17:25
  • OpenCVLoader.OPENCV_VERSION_(USE_LATEST_VERSION) – AMD Oct 01 '15 at 12:59
7

In most situations, a line like this before calling openCV is enough: "System.loadLibrary(Core.NATIVE_LIBRARY_NAME);"

DanielTheRocketMan
  • 3,199
  • 5
  • 36
  • 65
3

I was adding opencv in my project in Android Studio. This error occurs when native files are not available at run time. So you have to copy native files at correct location.

First create the jniLibs at this location /app/src/main/ location and copy the all the folder with *.so files (armeabi, armeabi-v7a, mips, x86) in the jniLibs from the OpenCV SDK and make your gradle plugin above 0.7.2+

enter image description here

Ajay S
  • 48,003
  • 27
  • 91
  • 111
2

The problem is that you are using Highgui.imread method before the OpenCV4Android library even finishes loading. Android calls the "onCreate" method before loading the OpenCV4Android library. So, create a separate method for your OpenCV code like this :-

public class Start extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_start);
   }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_start, menu);
    return true;
   }

public void readImage {
    Mat Image = Highgui.imread("/image.jpg");
    if(Image=null) {
    Log.i("Start", "--------Image Cannot be Loaded--------");
    else if(!Image=null) {
    Log.i("Start", "--------Image Loaded Successfully--------");
   }

}

h0tSPR1NG
  • 41
  • 1
  • 7
1

The link in the answer was not working and i had to dig around for sometime for the solution that worked for me.

I first had a BaseLoaderCallback defined in the class

private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");
               // any immediate code for using OpenCV
            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};

Then in onResume function i had:

@Override
public void onResume()
{
    super.onResume();
    if (!OpenCVLoader.initDebug()) {
        Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
    } else {
        Log.d(TAG, "OpenCV library found inside package. Using it!");
        mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);

    }
}

Make sure of the following

1.You are changing the OPENCV_VERSION_3_0_0 as per your version

  1. Not to run any opencv library before loading. Even in onCreate(), opencv has not yet loaded. Better to put it in the onManagerConnected() function in the switch case where OpenCV has loaded successfully.
Binil Jacob
  • 501
  • 6
  • 9
0

In my case I paste the opencv classes in wrong package name

Wrong one

I paste the opencv classes into com.opencv -> all classes

Correct one

org.opencv -> all classes

After change this right package name it will works.

Reason - they may refer "org.opencv.."

Ranjithkumar
  • 16,071
  • 12
  • 120
  • 159
0

I've spent several hours on this, and couldn't find a working solution. Here's what worked for me, check out my my answer I gave for a similar question..

https://stackoverflow.com/a/65832050/6212983

Harsha
  • 1,568
  • 2
  • 19
  • 22