如何在Android中解决NDK中的java.lang.UnsatisfiedLinkError?

时间:2010-07-16 06:32:45

标签: android-ndk

我是android中的ndk开发的新手。我已经通过了ndk android的文件系统。 在这里,解释我做了什么。 1)我创建了一个名为“jni”的文件夹,然后创建了一个名为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");
 }

但是现在当我在xp中使用cygwin构建它成功创建.so文件然后我作为android应用程序运行。它给了我LOGCAT中的java.lang.UnsatisfiedLinkError。

所以,请让我知道我错在哪里。

先谢谢,

12 个答案:

答案 0 :(得分:22)

我认为您忘记更改包名称。

Java_com_mindtherobot_samples_ndkfoo

您指定的创建项目应该是您的包。

答案 1 :(得分:21)

另外(刚遇到此问题),请注意,如果您在Intel Atom x86仿真器上进行测试,System.loadLibrary()将始终抛出异常。它适用于常规Android模拟器和物理设备上的调试。

答案 2 :(得分:11)

虽然这不是OP的问题,但由于缺少了我的java.lang.UnsatisfiedLink错误

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

答案 3 :(得分:5)

正如其他人所提到的,签名错误的可能性很大。

如果运行javah实用程序,则可以找到确切的签名。从项目中的bin文件夹(生成.apk)和生成Java类层次结构的根目录开始,运行:

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

...并且,如果你的包名和类名正确,它将为任何本机函数写出一个带有正确函数签名的头文件(名为jni_sig.h)。将其复制到标题和.c文件,根据需要添加参数,它应该可以正常工作。

答案 4 :(得分:4)

可能不再相关,但据我所知,您还需要在本机库名称中添加“lib”前缀。在您的情况下,您需要将Android.mk更改为 “LOCAL_MODULE:= libndkfoo”并保留“System.loadLibrary(”ndkfoo“);”原样。检查ndk示例代码。

答案 5 :(得分:3)

我很确定应该是:

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”。

您还可以在使用winrar或类似内容构建后打开APK文件,以确保libndkfoo.so文件实际上包含在包中。

无论哪种方式,如果您没有在NdkFooActivity中声明本机函数,您将收到该错误,即

public static native String invokeNativeFunction();

答案 6 :(得分:2)

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的模拟器中执行。 在与Android.mk相同的文件夹中创建一个名为application.mk的文件,并将其中一个放入其中:

  1. APP_ABI:= x86
  2. APP_ABI:= armeabi
  3. APP_ABI:= mips
  4. APP_ABI:= armeabi x86 mips //在所有目标中编译,你将获得3 * .so文件
  5. 然后编译 - >运行。 它应该工作。

答案 7 :(得分:1)

在jni文件夹中创建一个文件Application.mk。复制以下行并将其粘贴到Application.mk并保存。现在用cgywin构建项目并再次运行

APP_ABI:= armeabi armeabi-v7a

答案 8 :(得分:1)

方法名称Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction

可能与您的包名或类名不同。 要使方法的命名完全相同,您必须使用javah

这将生成一个头文件,该文件将具有所需的相同方法名称。要使此头文件转到项目bin中的classes文件夹(确保使用静态方法创建了java文件,并且通过终端

中的此命令正确构建它

~/workspace/Android_Example2/bin/classes$

在此目录中编写以下命令

sudo javah -jni com.NDK.android_example2.MainActivity

根据您的项目更改包名称和类名。这将在您的classes文件夹中创建com_NDK_android_example2_MainActivity.h。

只需将此文件移至jni文件夹即可。在此文件中,您将在MainActivity.java文件中创建静态方法,但它们只是声明未实现,您将在C文件中实现。

注意:在处理方法时,请检查是否需要声明方法参数,因此请在C文件中声明它们。

希望得到这个帮助。

答案 9 :(得分:0)

我也遇到java.lang.UnsatisfiedLinkError错误。我在上面的答案中验证了一切,但仍然出现错误。我最终发现JNI方法名称不能有下划线。

实施例: Java_com_example_app_NativeLib_print_out_stuff&lt; - 生成java.lang.UnsatisfiedLinkError:print_out_stuff

将print_out_stuff函数重命名为没有下划线的内容: Java_com_example_app_NativeLib_printOutStuff&lt; - 作品

答案 10 :(得分:0)

这是一个如何使用本机代码的教程:here

确保项目路径中没有任何空格。 您也无法在包或项目名称中使用下划线。

答案 11 :(得分:0)

替换此

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

重复所有这些步骤它应该工作:)