2014-07-04 18 views
8

Tôi đang phát triển một dự án Android bằng OpenCV. Một số phương pháp không có phiên bản Java, vì vậy tôi phải sử dụng NDK để sử dụng chúng trong dự án của tôi.JNI- java.lang.UnsatisfiedLinkError: Không tìm thấy phương thức gốc

Đây là lần đầu tiên tôi sử dụng NDK, vì vậy sau khi tìm kiếm một số ví dụ, tôi đã viết mã của tôi, chạy nó trên điện thoại của tôi, và nhận được thông báo lỗi dưới đây:

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) 

tôi tái sinh .so file trong vài lần, và kiểm tra việc đặt tên cho các hàm jni. Tôi cũng đã thêm các trình bao bọc 'extern' C '' vào các hàm jni. Nhưng không có giải pháp nào hiệu quả.

Lưu ý: Tôi luôn sử dụng Intellij Idea để phát triển các chương trình JAVA, và vì Idea không hỗ trợ NDK, và tôi phải sử dụng Eclipse để đến NDK, vì vậy ... đây cũng là lần đầu tiên tôi sử dụng Eclipse. Tôi có thể đã phạm nhiều sai lầm ngớ ngẩn. lol

Dưới đây là mã C++ và makefile của tôi.

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 và LocalFeatures.cpp không được hiển thị, nhưng tôi chắc chắn vấn đề không phải là với họ.

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) 

Những file cpp và các tập tin .mk đang ở trong một dự án Eclipse. libmytest_lib.so, libopencv_java.so, libnonfree.so có thể được tạo chính xác. Các tệp .java sau nằm trong dự án Intellij Idea. Tôi đã sao chép các tệp .so này vào \ lib trong dự án ý tưởng.

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

Một phần của 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*/ 
} 

Cảm ơn rất nhiều!

Trả lời

6

Sau khi làm theo lời khuyên của JonesV, tôi đã xóa tĩnh khỏi mã của mình. Nhưng sau đó, vấn đề vẫn tồn tại.

Cuối cùng tôi sửa lỗi chương trình của tôi của tôi, và khi chạy đến dòng này:

System.loadLibrary("opencv_java"); 

Chương trình đã ném một lỗi, thay vì chạy bình thường như tôi nghĩ. KIỂM SÁT THỰC HIỆN BẤT CỨ THỰC HIỆN: <

Bây giờ tôi đã tìm thấy một lỗi mà tôi chưa từng thấy trước đây.

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

Có nghĩa là, KHÔNG LIBS bị LOAD. Vì vậy, tôi đã kiểm tra cấu trúc dự án của mình, và thấy rằng tôi đặt các tệp .so của tôi trong thư mục libs /, thay vì libs/armeabi/folder.

Và giải pháp được tìm thấy ở đây: Android NDK java.lang.UnsatisfiedLinkError: findLibrary returned null bởi user1647750

2

Di static từ:

public static native int readImg(); 

tức là viết nó như thế này:

public native int readImg(); 

Nếu bạn thực sự muốn phương pháp readImg() của bạn được tĩnh, bạn nên khai báo phương pháp JNI như sau (với jclass thay vì jobject):

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

Bạn thế lve một nửa vấn đề của tôi, và cho tôi nhận ra rằng vấn đề không chỉ với mã của tôi, mà còn là cấu trúc dự án của tôi. Cảm ơn :) – pwwpche

+0

Thực ra, điều này không quan trọng. 'JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg (JNIEnv * env, jobject obj)' và 'JNIEXPORT jint JNICALL Java_com_example_MyTest_JNIlib_readImg (JNIEnv * env, jclass obj)', bởi vì trong C, ** jclass ** và ** jobject ** là các từ đồng nghĩa. –

+0

@SteveM bạn có thể xây dựng không? 'static' ẩn phương thức trên tất cả các thiết bị, trong khi ** jobject ** chỉ là' void * 'khi được sử dụng đúng. –

4

tôi thêm

extern "C" 

trước khi chức năng tuyên bố ví dụ:

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

thì lỗi đã biến mất

+0

số nhận dạng dự kiến ​​hoặc '(' –

Các vấn đề liên quan