Как решить java.lang.UnsatisfiedLinkError в NDK в Android? - PullRequest
25 голосов
/ 16 июля 2010

Я новичок в разработке ndk в android. Я прошел файловую систему ndk android. Здесь объясняю, что я наделал. 1) я создал папку с именем "jni", затем создал 2 файла с именами Android.mk и ndkfoo.c.

В Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Here we give our module name and source file(s)
LOCAL_MODULE    := ndkfoo
LOCAL_SRC_FILES := ndkfoo.c

include $(BUILD_SHARED_LIBRARY)

и в ndkfoo.c

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

jstring Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
 return (*env)->NewStringUTF(env, "Hello from native code!");
}

Затем я создал класс NdkFooActivity, в котором я написал

// load the library - name matches jni/Android.mk
 static {
  System.loadLibrary("ndkfoo");
 }

Но теперь, когда я собираюсь из cygwin в xp, он успешно создает файл .so, тогда я запускаюсь как приложение для Android. Это дает мне java.lang.UnsatisfiedLinkError в LOGCAT.

Итак, пожалуйста, дайте мне знать, где я не прав.

Заранее спасибо,

Ответы [ 12 ]

22 голосов
/ 09 марта 2011

Я думаю, что вы забыли изменить имя пакета.

Java_com_mindtherobot_samples_ndkfoo

Это должен быть ваш пакет, который вы указали при создании проекта.

21 голосов
/ 14 декабря 2012

Также (только что столкнулся с этой проблемой), обратите внимание, что System.loadLibrary () всегда выдает исключение, если вы тестируете на эмуляторе Intel Atom x86. Он отлично работает на обычных эмуляторах Android и отлаживается на физическом устройстве.

11 голосов
/ 20 января 2012

Хотя это не было проблемой ОП, у меня был тот же java.lang.UnsatisfiedLinkError из-за отсутствия

static {
    System.loadLibrary("mylibraryname");
}
5 голосов
/ 25 сентября 2010

Существует большая вероятность, что подпись неверна, как уже упоминали другие.

Если вы запустите утилиту javah, вы сможете найти точную подпись.Из папки bin в вашем проекте, где находится .apk и создан корень иерархии классов Java, выполните:

javah -o jni_sig.h com.mindtherobot.whwhat.your.package.is.NdkFooActivity

... и, если вы правильно указали имя пакета и имя класса, он запишет заголовок (называемый jni_sig.h) с правильными сигнатурами функций для любых собственных функций.Скопируйте его в свой заголовок и файл .c, добавив необходимые параметры, и он должен работать правильно.

4 голосов
/ 12 декабря 2012

Возможно, это больше не актуально, но, насколько я знаю, вам также необходимо добавить префикс "lib" к имени вашей нативной библиотеки.В вашем случае вам нужно изменить Android.mk на "LOCAL_MODULE: = libndkfoo" и оставить "System.loadLibrary (" ndkfoo ");"как есть.Проверьте пример кода ndk.

3 голосов
/ 13 января 2012

Я почти уверен, что должно быть:

JNIEXPORT jstring JNICALL Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
 return (*env)->NewStringUTF(env, "Hello from native code!");
}

На какой SDK вы ориентируетесь и какая у вас версия NDK?Полученная ошибка говорит о том, что она вообще не могла загрузить библиотеку или что был не реализованный метод?В любом случае убедитесь, что у вас нет android: hasCode = "false", установленного в теге приложения в вашем манифесте.

Вы также можете открыть файл APK после сборки, используя winrar или что-то подобное, чтобы убедиться, что файл libndkfoo.so действительно включен в пакет.

В любом случае, если вы нене объявляя нативную функцию в NdkFooActivity, вы получите эту ошибку, т.е.

публичная статическая нативная строка String invokeNativeFunction ();

2 голосов
/ 12 августа 2013
JNIEXPORT jstring JNICALL Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
 return (*env)->NewStringUTF(env, "Hello from native code!");
}

проблема в том, что вы компилируете для целевого процессора и выполняете в другом. если вы компилируете в ARM (armeabi), то выполните в эмуляторе на основе armeabi. создайте файл с именем application.mk в той же папке, что и Android.mk, и вставьте в него одно из следующих:

  1. APP_ABI: = x86
  2. APP_ABI: = armeabi
  3. APP_ABI: = mips
  4. APP_ABI: = armeabi x86 mips // для компиляции во всех целях, и вы получите 3 * .so файла

затем скомпилируйте-> запустите. это должно работать.

1 голос
/ 11 июня 2013

Имя метода Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction

может отличаться от имени вашего пакета или имени класса.Чтобы сделать это имя метода точно таким же, вы должны использовать javah.

. Это создаст файл заголовка, который будет иметь то же имя, что и необходимый метод. Чтобы сделать этот файл заголовка, перейдите в папку классов вbin вашего проекта (убедитесь, что вы создали Java-файл со статическим методом и правильно его построили) этой командой в вашем терминале

~/workspace/Android_Example2/bin/classes$

В этом каталоге напишите следующую команду

sudo javah -jni com.NDK.android_example2.MainActivity

Измените имя пакета и имя класса в соответствии с вашим проектом. Это создаст com_NDK_android_example2_MainActivity.h в папке ваших классов.

Просто переместите этот файл в папку jni.В этом файле будут статические методы, которые вы создали в файле MainActivity.java, но они просто объявлены как не реализованные, которые вы реализуете в своем файле C.

ПРИМЕЧАНИЕ. При копировании метода убедитесь, что параметры метода необходимо объявить, поэтому сделайте так, чтобы они объявлялись в вашем файле C.

Надеюсь, эта справка.

1 голос
/ 25 ноября 2012

Создайте файл Application.mk в папке jni. Скопируйте следующую строку и вставьте его в Application.mk и сохраните. Теперь соберите проект с помощью вашего cgywin и снова запустите

APP_ABI: = armeabi armeabi-v7a

0 голосов
/ 28 июля 2013

Замените это

Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction

на

Java_your_packege_name_your_Activity_Name_invokeNativeFunction

Пример, если ваш пакет com.pack и имя активности - MainActivity, тогда

Java_com_pack1_MainActivity_invokeNativeFunction 

Нене забудьте добавить ссылку в Activity.

// загрузить библиотеку - имя соответствует jni / Android.mk

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

 public native String invokeNativeFunction();

Повторите все эти шаги, это должно работать :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...