【问题标题】:Unsatisfied Link Error - OpenCV for Android Non-native不满意的链接错误 - OpenCV for Android Non-native
【发布时间】:2012-08-09 23:18:07
【问题描述】:

几天前,我 asked 关于 UnsatisfiedLinkError 运行非本地 OpenCV 代码。我以为在重新安装 Eclipse 并关闭/重新打开所有包后问题就解决了,但是在我将 OpenCV 代码放入现有的 onCreate() 方法后又回来了。

我创建了一个新的 Android 应用程序,其中包含一个名为 Start 的活动。然后我转到项目属性并将 OpenCV 添加为库。这是活动的代码 (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;
    }
}

这是日志:

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)

同样,这是非本地代码,因此出现 Unsatisfied Link Error 没有多大意义。

【问题讨论】:

  • 但这是 java 包装器,因此它从 Java 代码调用本机 (c++) 函数。确保您的 apk 包含 opencv_java.so
  • 你也可以在这里问这个问题:answers.opencv.org/questions官方openCV wiki,似乎是仿照stackoverflow。
  • @Astor 我意识到虽然目录结构完好无损,但版本控制已经删除了实际的库,所以我不得不替换它们。好决定!不幸的是,我仍然遇到同样的错误。我在 \OpenCV\sdk\native\libs\ 中有三个版本的 libopencv_java.so:一个在 \armeabi,一个在 armeabi-v7a,一个在 \x86。
  • @lain_b 好主意,我也去那里问问。

标签: android opencv unsatisfiedlinkerror


【解决方案1】:

我已经为此花费了几个小时,但找不到有效的解决方案。 这对我有用,请查看我对类似问题的回答。

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

【讨论】:

    【解决方案2】:

    在我的例子中,我将 opencv 类粘贴到错误的包名中

    一个错误

    我将 opencv 类粘贴到 com.opencv -> 所有类

    正确一个

    org.opencv -> 所有类

    更改此正确的包名称后,它将起作用。

    原因 - 他们可能参考“org.opencv..”

    【讨论】:

      【解决方案3】:

      答案中的链接不起作用,我不得不四处寻找适合我的解决方案。

      我首先在类中定义了一个 BaseLoaderCallback

      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;
              }
          }
      };
      

      然后在 onResume 函数中我有:

      @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);
      
          }
      }
      

      确保以下几点

      1.您正在根据您的版本更改 OPENCV_VERSION_3_0_0

      1. 在加载之前不要运行任何 opencv 库。即使在onCreate(),opencv 还没有加载。最好将它放在 OpenCV 已成功加载的 switch case 中的onManagerConnected() 函数中。

      【讨论】:

        【解决方案4】:

        经过一番搜索,我找到了this

        "3.如果您的应用项目没有JNI部分,只需将相应的OpenCV原生库从/sdk/native/libs/复制到您的项目目录到文件夹libs/中即可。"

        这意味着复制 \armeabi、\armeabi-v7a 和 \x86 文件夹。

        "4. 在您​​的应用程序中启用 OpenCV 的最后一步是调用 OpenCV API 之前的 Java 初始化代码。例如,可以在 Activity 类的静态部分中完成,该部分仅在执行任何操作之前执行一次创建类的实例:

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

        或者,您可以将其放在 onCreate 方法中:

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

        现在可以了!

        【讨论】:

        • 静态块在 onCreate 中创建时显示错误。它说添加“EnumBody”以完成块..这是什么意思?我仍然收到 unsatisfiedLinkError ..
        • 静态部分为我完成了这项工作。当然应该把它放在方法之外,放在主要活动本身中。
        • @1" 我尝试了上面提到的相同方法。执行程序时出现异常。java.lang.UnsatisfiedLinkError: Native method not found: org.opencv.highgui.Highgui.imread_1:(Ljava/lang/String;)J
        • @TGMCians 你确定在<yourapp>\libs\armeabi-v7a 下有libopencv_highgui.a 吗? OpenCVLoader.initDebug() 成功了吗?
        • 成功了,我将 *.so 文件复制到 Android Studio 的错误位置,谢谢
        【解决方案5】:

        我在 Android Studio 的项目中添加了 opencv。当本机文件在运行时不可用时,会发生此错误。所以你必须在正确的位置复制原生文件。

        首先在此位置/app/src/main/ 位置创建jniLibs,然后从OpenCV SDK 的jniLibs 中复制所有带有*.so 文件(armeabi、armeabi-v7a、mips、x86)的文件夹并制作你的gradle 插件0.7.2+以上

        【讨论】:

        • 非常感谢。除了这个之外,所有解决方案对我来说都失败了。谢谢你:)
        【解决方案6】:

        在大多数情况下,在调用 openCV 之前这样一行就足够了: "System.loadLibrary(Core.NATIVE_LIBRARY_NAME);"

        【讨论】:

        • 这仅适用于Java项目,它不适用于android。
        【解决方案7】:

        问题是您在 OpenCV4Android 库完成加载之前就使用了 Highgui.imread 方法。 Android 在加载 OpenCV4Android 库之前调用“onCreate”方法。因此,为您的 OpenCV 代码创建一个单独的方法,如下所示:-

        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--------");
           }
        

        }

        【讨论】:

          【解决方案8】:

          你应该使用

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

          在 OnCreate() 中 并使用

          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;
                      }
              }
              };
          

          【讨论】:

          • 在从 opencv 声明一个类型的成员时,这给了我许多不满意的链接异常。静态初始化有帮助。
          • OpenCVLoader.OPENCV_VERSION_(USE_LATEST_VERSION)
          猜你喜欢
          • 2014-03-26
          • 2016-04-26
          • 1970-01-01
          • 2012-04-22
          • 2013-09-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多