Неудовлетворённая ссылка в андроиде (затмение) - PullRequest
6 голосов
/ 15 июня 2011

Я пытаюсь запустить простой код jni в Android, но все, что я получаю Unsatisfiedlinkerror.

Вот мой код Java:

package com.lipcap;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
/** Called when the activity is first created. */

TextView a;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    a=new TextView(this);

    String b; 
    MainActivity ob=new MainActivity();
    b=ob.sniff();

    a.setText(b);

    setContentView(a);
}
public native String sniff();

    static{
        System.loadLibrary("native");
    }


} 

А вот мой код C ++ (в $ PROJECT_PATH / jni /):

#include<iostream>
#include<string.h>
#include<jni.h>
JNIEXPORT jstring JNICALL Java_com_lipcap_MainActivity_sniff
(JNIEnv *env, jobject obj){
       return env->NewStringUTF("This is Native");
}

Я выполнил java-код, используя javac, и сделал заголовок, используя javah.

Затем я запустил ndk-build. И тогда я запустил код из Eclipse. (Установленный APK в Android).

Я получаю эту ошибку:

E/AndroidRuntime(  769): FATAL EXCEPTION: main
E/AndroidRuntime(  769): java.lang.UnsatisfiedLinkError: sniff
E/AndroidRuntime(  769):    at com.lipcap.MainActivity.sniff(Native Method)
E/AndroidRuntime(  769):    at com.lipcap.MainActivity.onCreate(MainActivity.java:36)
E/AndroidRuntime(  769):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
E/AndroidRuntime(  769):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
E/AndroidRuntime(  769):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
E/AndroidRuntime(  769):    at android.app.ActivityThread.access$2300(ActivityThread.java:125)
E/AndroidRuntime(  769):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
E/AndroidRuntime(  769):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(  769):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  769):    at android.app.ActivityThread.main(ActivityThread.java:4627)
E/AndroidRuntime(  769):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(  769):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(  769):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime(  769):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime(  769):    at dalvik.system.NativeStart.main(Native Method)

Я не установил LD_LIBRARY_PATH.

Однако без установки образца кода LD_LIBRARY_PATH, такого как HelloJNI, предоставленного NDK, все работает нормально.

Пожалуйста, скажите мне, где я скучаю.

Ответы [ 3 ]

12 голосов
/ 01 июля 2011

Ричард-Хед, как вы упомянули: "При изменении кода с C ++ на C все работает отлично" ...

Меня мучила одна и та же проблема в течение нескольких дней, и я удостоверился, что все набранное мной (naming, Android.mk и т. Д.) Не имеет проблем. Всякий раз, когда в C, я в порядке. Пока я перехожу на cpp, UnsatisfiedLinkError.

Я наконец-то получил подсказку по этой ссылке: http://markmail.org/message/fhbnprmp2m7ju6lc

Это все из-за искажения имени в C ++! Эта же функция, если у вас нет extern "C", окружающих ее в файле .cpp, имя искажено, поэтому JNI не может найти имя функции, поэтому появляется UnsatisfiedLinkError.

Наденьте и снимите extern "C" { } вокруг ваших функций, запустите nm obj/local/armeabi/libnative.so, вы четко увидите ту же функцию без и с искажением имени.

Надеюсь, это поможет и другим с такой же проблемой.

0 голосов
/ 15 сентября 2014

Я дам еще один совет. Я уже получал эту же ошибку раньше, но решил эту проблему с помощью "Кулинарной книги Android Native Development Kit". Обратите внимание на эти утверждения;

Собственная функция должна следоватьконкретный шаблон для имени пакета, имени класса и имени метода. Пакет и имя класса должны согласовываться с пакетом и именем класса Java-класса, из которого вызывается нативный метод, а имя метода должно совпадать с именем методаИмя объявлено в этом классе Java.Это помогает виртуальной машине Dalvik находить собственную функцию во время выполнения. Несоблюдение этого правила приведет к UnsatisfiedLinkError во время выполнения.

Например, для выше

Вам необходимо изменить свою функциюимя как (не используйте com.bla в именах пакетов, если вы сосредоточены на NDK)

#include<iostream>
#include<string.h>
#include<jni.h>

JNIEXPORT jstring JNICALL Java_lipcap_example_MainActivity_sniff
(JNIEnv *env, jobject obj){
       return env->NewStringUTF("This is Native");
}
0 голосов
/ 15 июня 2011

На самом деле это не совсем правильно ...

Попробуйте:

package com.lipcap;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
    /** Called when the activity is first created. */

    TextView a;

    public native String sniff();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        a=new TextView(this);

        String b = sniff(); 

        a.setText(b);

        setContentView(a);
    }

    static{
        System.loadLibrary("native");
    }

}

Наконец ... это в вашем Android.mk?

LOCAL_MODULE    := native
...