Неудовлетворенная ошибка связи - OpenCV для Android
Несколько дней назад я спросил об UnsatisfiedLinkError
от запуска неродного кода OpenCV. Я подумал, что проблема решена после переустановки Eclipse и закрытия/повторного открытия всех пакетов, но она снова появилась после того, как я поместил код OpenCV в существующий метод onCreate()
.
Я создал новое приложение для Android с активностью "Старт". Затем я перешел к свойствам проекта и добавил 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 не имеет большого смысла.
Ответы
Ответ 1
После кучи поиска я нашел this:
"3. Если ваш проект приложения не имеет части JNI, просто скопируйте соответствующие родные библиотеки OpenCV из/sdk/native/libs/в каталог проекта в папку libs/."
Таким образом, это означает скопировать папки \armeabi,\armeabi-v7a и\x86.
"4. Последним шагом включения OpenCV в ваше приложение является код инициализации Java перед вызовом OpenCV API. Это можно сделать, например, в статическом разделе класса 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
}
[...]
}
Теперь он работает!
Ответ 2
вы должны использовать
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;
}
}
};
Ответ 3
В большинстве ситуаций такая строка перед вызовом openCV достаточно:
"System.loadLibrary(Core.NATIVE_LIBRARY_NAME);"
Ответ 4
Проблема заключается в том, что вы используете метод Highgui.imread до того, как библиотека OpenCV4Android даже закончит загрузку. Android загружает метод onCreate перед загрузкой библиотеки OpenCV4Android. Итак, создайте отдельный метод для вашего кода 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--------");
}
}
Ответ 5
Я добавлял opencv в свой проект в Android Studio. Эта ошибка возникает, когда собственные файлы недоступны во время выполнения. Поэтому вам нужно скопировать собственные файлы в правильном месте.
Сначала создайте jniLibs
в этом местоположении /app/src/main/
и скопируйте всю папку с *.so файлами (armeabi, armeabi-v7a, mips, x86) в jniLibs из SDK OpenCV и сделайте свой gradle плагин выше 0.7.2 +
![enter image description here]()
Ответ 6
Ссылка в ответе не работала, и мне пришлось когда-нибудь копаться в решении, которое сработало для меня.
Сначала у меня был 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 согласно вашей версии
- Не загружать библиотеку opencv перед загрузкой. Даже в
onCreate()
opencv еще не загружен. Лучше поместить его в функцию onManagerConnected()
в случае коммутатора, где OpenCV успешно загружен.