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

问题描述:

我是在android.nd中开发的ndk新手,我经历了ndk android的文件系统。 在这里,解释我做了什么。 1)我创建了一个名为“jni”的文件夹,然后创建2个名为Android.mk和ndkfoo.c的文件。如何在Android中解决NDK中的java.lang.UnsatisfiedLinkError?

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

所以,请让我知道我错了。

在此先感谢,

+0

您确定您声明invokeNativeFunction()的类实际上是com.mindtherobot.samples.ndkfoo.NdkFooActivity?您可以发布所有代码 – ognian 2010-07-17 19:14:11

+2

具体而言,请在.java文件中包含本地方法的声明。也显示“包”和“类”声明。另外,将JNI_OnLoad函数添加到共享库中,并在其中放入一些日志记录,以便确保该库成功加载。 – fadden 2010-07-19 17:47:53

+0

在ndkfoo.c中检查此声明Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction,这应该更改为您的软件包名称,如Java_com_your_package_ndkfoo_NdkFooActivity_invokeNativeFunction – pradeep 2011-04-30 11:31:49

像其他人提到的那样,签名是错误的。

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

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

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

+1

谢谢。在我的系统上,它需要从Classes子目录运行。 – weston 2012-09-04 17:39:38

我想你忘了更改包名。

Java_com_mindtherobot_samples_ndkfoo

它应该是你的包你所指定的创建项目。

我敢肯定这应该是:

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你会得到错误,即

公共静态本地字符串invokeNativeFunction();

虽然这不是OP的问题,但我有相同的java.lang。UnsatisfiedLinkError由于缺少

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

通常它会导致以下问题:'java.lang.ExceptionInInitializerError java.lang.UnsatisfiedLinkError:Library xyz ... not found' – ademar111190 2012-11-13 18:09:40

+0

如何在上述情况下解决它? – Ahmed 2013-02-21 21:30:40

创建JNI folder.Copy文件Application.mk以下行并将其粘贴到Application.mk和save.Now建立与您cgywin项目,然后再次运行

APP_ABI的: = armeabi armeabi-v7a

也许不相关了,但据我所知,你还需要添加“lib”前缀到你的本地库名称。在你的情况下,你需要将Android.mk更改为 “LOCAL_MODULE:= libndkfoo”并保留“System.loadLibrary(”ndkfoo“);”就这样。检查ndk示例代码。

+0

它不能解决仍然存在的问题...... – 2013-10-07 18:32:03

另外(只是遇到了这个问题),请注意,如果您在Intel Atom x86仿真器上测试,System.loadLibrary()将始终引发异常。它适用于普通的Android仿真器,并在物理设备上进行调试。

+0

+1帮助。你怎么知道这件事的? – quinestor 2013-07-11 13:04:21

+2

@Daniel Rodriguez:谢谢soooooooooo。 :) :) :) – 2013-07-13 09:36:32

+0

+1,是的,你是怎么知道的? – 2013-11-08 16:21:25

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

例子: Java_com_example_app_NativeLib_print_out_stuff < - 生成java.lang.UnsatisfiedLinkError中:print_out_stuff

重命名print_out_stuff功能的东西没有下划线: Java_com_example_app_NativeLib_printOutStuff < - 工程

这里有一个教程如何使用本机代码:here

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

方法名Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction

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

这将创建一个头文件,它将具有所需的相同方法名称。要将此头文件转到项目bin的classes文件夹中(确保已使用静态方法创建了java文件而在终端

~/workspace/Android_Example2/bin/classes$

构建得当)该命令在该目录中根据写下面的命令

sudo javah -jni com.NDK.android_example2.MainActivity 

更改包名和类名的project.This将在您的classes文件夹中创建一个com_NDK_android_example2_MainActivity.h。

只需将此文件移动到您的jni文件夹。在这个文件中,将会有在MainActivity.java文件中创建的静态方法,但是它们只是声明没有实现,您将在您的C文件中实现。

注意:虽然应对方法检查方法参数是需要声明的,所以让他们声明在您的C文件中。

希望得到这个帮助。

,如果你的包是com.pack和活动名称的名字是MainActivity然后

Java_com_pack1_MainActivity_invokeNativeFunction 

不要忘记添加引用替换此

Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction 

随着

Java_your_packege_name_your_Activity_Name_invokeNativeFunction 

例在活动中。

//加载库 - 名称相匹配的JNI/Android.mk

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

public native String invokeNativeFunction(); 

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

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:= 86
  2. APP_ABI:= armeabi
  3. APP_ABI:= MIPS
  4. APP_ABI:= armeabi x86 mips //在所有目标中进行编译,您将获得3 * .so文件

然后编译 - >运行。 它应该工作。

+0

在真实设备中执行,并且工作正常。谢谢.... – 2016-09-26 06:13:51