2010-07-16 62 views
24

我是在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

回答

5

像其他人提到的那樣,簽名是錯誤的。

如果您運行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

23

我想你忘了更改包名。

Java_com_mindtherobot_samples_ndkfoo

它應該是你的包你所指定的創建項目。

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你會得到錯誤,即

公共靜態本地字符串invokeNativeFunction();

11

雖然這不是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

1

創建JNI folder.Copy文件Application.mk以下行並將其粘貼到Application.mk和save.Now建立與您cgywin項目,然後再次運行

APP_ABI的: = armeabi armeabi-v7a

4

也許不相關了,但據我所知,你還需要添加「lib」前綴到你的本地庫名稱。在你的情況下,你需要將Android.mk更改爲 「LOCAL_MODULE:= libndkfoo」並保留「System.loadLibrary(」ndkfoo「);」就這樣。檢查ndk示例代碼。

+0

它不能解決仍然存在的問題...... – 2013-10-07 18:32:03

20

另外(只是遇到了這個問題),請注意,如果您在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

0

我也有一個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 < - 工程

0

這裏有一個教程如何使用本機代碼:here

確保您的項目路徑中沒有任何空格。 你也不能在你的包或項目名稱中使用下劃線。

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 

更改包名和類名的project.This將在您的classes文件夾中創建一個com_NDK_android_example2_MainActivity.h。

只需將此文件移動到您的jni文件夾。在這個文件中,將會有在MainActivity.java文件中創建的靜態方法,但是它們只是聲明沒有實現,您將在您的C文件中實現。

注意:雖然應對方法檢查方法參數是需要聲明的,所以讓他們聲明在您的C文件中。

希望得到這個幫助。

0

,如果你的包是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(); 

重複這些步驟應該工作:)

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:= 86
  2. APP_ABI:= armeabi
  3. APP_ABI:= MIPS
  4. APP_ABI:= armeabi x86 mips //在所有目標中進行編譯,您將獲得3 * .so文件

然後編譯 - >運行。 它應該工作。

+0

在真實設備中執行,並且工作正常。謝謝.... – 2016-09-26 06:13:51