No implementation found for native / UnsatisfiedLinkError makes me crazy

时间:2015-06-15 14:23:08

标签: android android-ndk java-native-interface unsatisfiedlinkerror

I'm having problem with this JNI thing...

I'm dealing with an FPGA and an Android device, and to make them communicate I use JNI library. There is 7-segment Controller in FPGA and Android-to-FPGA driver also.

But I found myself stuck in this implementation hell... and yes, I searched and searched. But most answer was "Look for the naming convention" or "Make sure you are referring .so file". I think I'm not in that case...

First here is my .java android code :

package com.hanback.segment;


import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class SegmentActivity extends Activity {

private int CountNumber;
private int flag = 0;
private boolean stop = false;

static{ System.loadLibrary("7segment"); } 

public native int SegmentControl(int data);
public native int SegmentStateControl(int data);

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_segment);
    CountNumber = 0;    

    SegmentControl(0);
    final Button Start = (Button) findViewById(R.id.butStart);
    final Button Set = (Button) findViewById(R.id.butSet);
    final Button Stop = (Button) findViewById(R.id.butStop);
    final EditText Ctno = (EditText) findViewById(R.id.etCountNo);  


    Start.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {

            if (Ctno.getText().toString().getBytes().length <= 0) {
                Toast.makeText(getApplicationContext(), R.string.error_ctrnotset,
                        Toast.LENGTH_SHORT).show();
                return;
            }           
            else if (CountNumber <= 0 || CountNumber >= 1000000){
                Toast.makeText(getApplicationContext(), R.string.error_ctrvalerr,
                        Toast.LENGTH_SHORT).show();
                return;
            }   
            SegmentStateControl(1);
        }
    });

    Set.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {

            if (Ctno.getText().toString().getBytes().length <= 0) {
                Toast.makeText(getApplicationContext(), R.string.error_ctrnotset,
                        Toast.LENGTH_SHORT).show();
                return;
            }
            else 
                CountNumber = Integer.parseInt(Ctno.getText().toString());

            if (CountNumber <= 0 || CountNumber >= 1000000){
                Toast.makeText(getApplicationContext(), R.string.error_ctrvalerr,
                        Toast.LENGTH_SHORT).show();
                return;
            }

            CountNumber = Integer.parseInt(Ctno.getText().toString());

            SegmentStateControl(0);             
            SegmentControl(CountNumber);
        }
    });

    Stop.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View v) {

            SegmentStateControl(0);

        }
    });     

}
}

Then c code : (header skipped)

extern "C"{
jint Java_com_hanback_segment_SegmentActivity_SegmentControl(JNIEnv*  env, jobject thiz, jint data) {
    int dev, ret;
    dev = open("/dev/segment",O_RDWR | O_SYNC);

    if(dev != -1) {
        ret = write(dev, &data, 4); // write is pre-defined FPGA driver function
        close(dev);
    } else {
        __android_log_print(ANDROID_LOG_ERROR, "SegmentActivity", "Device Open ERROR!\n");
        exit(1);
    }

    return 0;
}

jint Java_com_hanback_segment_SegmentActivity_SegmentStateControl(JNIEnv* env, jobject thiz, jint data) {
    int dev, ret;

    dev = open("/dev/segment". O_RDWR | O_SYNC);

    if(dev != 1) {
        ret = ioctl(dev, data, NULL, NULL); // ioctl is pre-defined FPGA driver function
        close(dev);
    } else {
        __android_log_print_(ANDROID_LOG_ERROR, "SegmentActivitiy", "Device Open ERROR!\n");
        exit(1);
    }
}
}

And Android.mk and Application.mk has no error...

Finally Logcat error message :

01-01 15:07:02.429: D/dalvikvm(1318): Trying to load lib /data/data/com.hanback.segment/lib/lib7segment.so 0x40514760
01-01 15:07:02.429: D/dalvikvm(1318): Added shared lib /data/data/com.hanback.segment/lib/lib7segment.so 0x40514760
01-01 15:07:02.429: D/dalvikvm(1318): No JNI_OnLoad found in /data/data/com.hanback.segment/lib/lib7segment.so 0x40514760, skipping init
01-01 15:07:02.449: W/dalvikvm(1318): No implementation found for native Lcom/hanback/segment/SegmentActivity;.SegmentControl (I)I
01-01 15:07:02.457: D/AndroidRuntime(1318): Shutting down VM
01-01 15:07:02.457: W/dalvikvm(1318): threadid=1: thread exiting with uncaught exception (group=0x40015560)
01-01 15:07:02.460: E/AndroidRuntime(1318): FATAL EXCEPTION: main
01-01 15:07:02.460: E/AndroidRuntime(1318): java.lang.UnsatisfiedLinkError: SegmentControl
01-01 15:07:02.460: E/AndroidRuntime(1318):     at com.hanback.segment.SegmentActivity.SegmentControl(Native Method)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at com.hanback.segment.SegmentActivity.onCreate(SegmentActivity.java:40)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.os.Looper.loop(Looper.java:130)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at android.app.ActivityThread.main(ActivityThread.java:3683)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at java.lang.reflect.Method.invokeNative(Native Method)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at java.lang.reflect.Method.invoke(Method.java:507)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
01-01 15:07:02.460: E/AndroidRuntime(1318):     at dalvik.system.NativeStart.main(Native Method)

I'm a beginner for JNI and this has blown my 1.5 days... Please help me T_T

1 个答案:

答案 0 :(得分:1)

声明你的功能:

    This is the first time this instance runs
    this is not really a new instance

JNIEXPORT宏用于使您的函数在.so文件的动态表中可见,以便Java可以在运行时链接它们。 JNICALL用于声明调用约定。