2014-07-04 18 views
8

Pracuję nad projektem Android przy użyciu OpenCV. Niektóre metody nie mają wersji Java, więc muszę użyć NDK, aby użyć ich w moim projekcie.JNI- java.lang.UnsatisfiedLinkError: Natywna metoda nie została znaleziona

To jest mój pierwszy raz przy użyciu NDK, więc po wyszukaniu niektórych przykładach, napisałem mój kod, uruchom go w urządzeniu i otrzymał komunikat o błędzie poniżej:

07-04 10:26:19.555 21270-21270/com.example.MyTest E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    java.lang.UnsatisfiedLinkError: Native method not found: com.example.MyTest.JNIlib.readImg:()I 
      at com.example.MyTest.JNIlib.readImg(Native Method) 
      at com.example.MyTest.MyActivity$2.onClick(MyActivity.java:60) 
      at android.view.View.performClick(View.java:4211) 
      at android.view.View$PerformClick.run(View.java:17267) 
      at android.os.Handler.handleCallback(Handler.java:615) 
      at android.os.Handler.dispatchMessage(Handler.java:92) 
      at android.os.Looper.loop(Looper.java:137) 
      at android.app.ActivityThread.main(ActivityThread.java:4898) 
      at java.lang.reflect.Method.invokeNative(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:511) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 
      at dalvik.system.NativeStart.main(Native Method) 

I zregenerowany .so plików na kilka razy i sprawdź nazewnictwo funkcji jni. Dodałem także "zewnętrzne" C "" opakowania do funkcji jni. Ale żadne z tych rozwiązań nie zadziałało.

Uwaga: Zawsze używam Intellij Idea do tworzenia programów JAVA, a ponieważ Idea nie obsługuje NDK, a ja muszę korzystać z Eclipse, aby dostać się do NDK, więc ... to jest także pierwszy raz, kiedy używam Eclipse. Mogłem popełnić wiele głupich błędów. lol

Poniżej znajdują się moje kody C++ i plik Makefile.

LocalMain.cpp

#include <stdio.h> 
#include <iostream> 
#include <opencv2/nonfree/nonfree.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/nonfree/features2d.hpp> 

#include <opencv2/opencv.hpp> 
#include <jni.h> 
#include <android/log.h> 
#include "LocalFeature.h" 
using namespace cv; 
using namespace std; 



int readImg() 
{ 
    /* do something*/ 

    return 0; 
} 


// JNI interface functions, be careful about the naming. 
extern "C" 
{ 
    JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg(JNIEnv * env, jobject obj); 
}; 

JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg(JNIEnv * env, jobject obj) 
{ 
    return (jint)readImg(); 
} 

LocalFeatures.h i LocalFeatures.cpp nie są pokazane, ale jestem pewien, że problem nie jest z nimi.

Android.mk

LOCAL_PATH:= $(call my-dir) 

include $(CLEAR_VARS) 
LOCAL_MODULE := nonfree_prebuilt 
LOCAL_SRC_FILES := libnonfree.so 
include $(PREBUILT_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_MODULE := opencv_java_prebuilt 
LOCAL_SRC_FILES := libopencv_java.so 
include $(PREBUILT_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
# Modify LOCAL_C_INCLUDES with your path to OpenCV for Android. 
LOCAL_C_INCLUDES:= E:/Java/libs/OpenCV-2.4.9-android-sdk/sdk/native/jni/include 
LOCAL_MODULE := mytest_lib 
LOCAL_CFLAGS := -Werror -O3 -ffast-math 
LOCAL_LDLIBS += -llog -ldl 
LOCAL_SHARED_LIBRARIES := nonfree_prebuilt opencv_java_prebuilt 
LOCAL_SRC_FILES := LocalMain.cpp \ 
LocalFeature.h \ 
LocalFeature.cpp 

include $(BUILD_SHARED_LIBRARY) 

te pliki .cpp i pliki .mk są w ramach projektu Eclipse. libmytest_lib.so, libopencv_java.so, libnonfree.so może być poprawnie wygenerowany. Następujące pliki .java znajdują się w projekcie Intellij Idea. Skopiowałem te pliki .so do \ lib w projekcie Idea.

JNIlib.java

public class JNIlib { 
    static 
    { 
     try 
     { 
      // Load necessary libraries. 
      System.loadLibrary("opencv_java"); 
      System.loadLibrary("nonfree"); 
      System.loadLibrary("mytest_lib"); 
     } 
     catch(UnsatisfiedLinkError e) 
     { 
      System.err.println("Native code library error.\n"); 
     } 
    } 
    public static native int readImg(); 
} 

Część MainActivity.java

public class MyActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2{ 

    public View.OnClickListener onClickListener = new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      JNIlib.readImg(); 
     } 
    }; 

    /*Other irrevelant code*/ 
} 

Dzięki wielkie!

Odpowiedz

6

Po wykonaniu porady JonesV, usunąłem statyczne z mojego kodu. Ale potem problem nadal istnieje.

końcu debugowany mój mój program, a gdy działa na tej linii:

System.loadLibrary("opencv_java"); 

Program wyrzucił błąd, zamiast pracuje normalnie, jak myślałem. NAPRAWDĘ GŁUPA POMYŁKA: <

Teraz, gdy znalazłem błąd, którego nigdy wcześniej nie zauważyłem.

java.lang.UnsatisfiedLinkError: Couldn't load opencv_java: findLibrary returned null 

Co oznacza, ŻADNE USTAWIENIA NIE MA ZAŁADOWANIA. Sprawdziłem więc strukturę mojego projektu i odkryłem, że umieszczam moje pliki .so w katalogu libs/zamiast katalogu libs/armeabi /.

i roztwór znaleźć tutaj: Android NDK java.lang.UnsatisfiedLinkError: findLibrary returned null przez user1647750

2

Usuń static od:

public static native int readImg(); 

tj napisać to tak:

public native int readImg(); 

Jeśli naprawdę chcesz, żeby Twój metoda readImg() być statyczne, należy zadeklarować metodę JNI następująco (z jclass zamiast jobject):

JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg(JNIEnv * env, jclass obj); 
+0

Jesteś tak w połowie mojego problemu, i pozwolę sobie uświadomić, że problem dotyczy nie tylko mojego kodu, ale także mojej struktury projektu. Dzięki :) – pwwpche

+0

Właściwie to nie ma znaczenia. 'JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg (JNIEnv * env, jobject obj)' i 'JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg (JNIEnv * env, jclass obj)', ponieważ w C, ** jclass ** i ** jobject ** są synonimami. –

+0

@SteveM możesz rozwinąć? 'static' ukrywa metodę na wszystkich urządzeniach, podczas gdy ** jobject ** jest tylko' void * ', gdy jest używane poprawnie. –

4

dodałem

extern "C" 

przed funkcje zadeklarować Ex:

extern "C" 
jstring 
Java_lara_myapplication_MainActivity_stringFromJNI(
     JNIEnv *env, 
    jobject /* this */) { 
    std::string hello = "Hello from C++"; 
    return env->NewStringUTF(hello.c_str()); 
} 

wtedy błąd zniknął

+0

oczekiwany identyfikator lub "(" –

Powiązane problemy