我是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。
所以,请让我知道我错在哪里。
先谢谢,
答案 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的文件,并将其中一个放入其中:
然后编译 - >运行。 它应该工作。
答案 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();
重复所有这些步骤它应该工作:)