Android JNI和NDK學習(02)--靜態方式實現JNI
JNI包括兩種實現方法:靜態和動態。兩種方法的區別如下:
靜態:先由Java得到本地方法的聲明,然后再通過JNI實現該聲明方法。
動態:先通過JNI重載JNI_OnLoad()實現本地方法,然后直接在Java中調用本地方法。
本文介紹靜態實現方式,下一篇會介紹動態實現方式。
1 首先,在Eclipse下新建一個工程myndk
Myndk.java的代碼如下:

1 package com.skywang.ndk; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.widget.TextView; 6 7 public class Myndk extends Activity { 8 9 @Override 10 public void onCreate(Bundle savedInstanceState) 11 { 12 super.onCreate(savedInstanceState); 13 14 TextView myTextView = new TextView(this); 15 myTextView.setText( HelloNdk() ); 16 setContentView(myTextView); 17 } 18 19 public native String HelloNdk(); 20 21 static { 22 System.loadLibrary("hello_jni"); 23 } 24 }
2 運行工程,生成.class文件
檢查bin目錄,若有生成Myndk.class;則繼續下一步。生成.class文件的目的,是為下一步生成.h頭文件做准備。
3 編譯生成.h文件
打開終端,切換到工程所在目錄。假設工程目錄為“/hom/skywang/workspace/ndk/myndk”,則通過以下命令切換目錄:
$ cd /home/skywang/workspace/ndk/myndk/
查看文件列表
$ ls
$ AndroidManifest.xml assets bin gen proguard-project.txt project.properties res src
新建jni目錄,並查看文件列表
$ mkdir jni; ls
$ AndroidManifest.xml assets bin gen jni proguard-project.txt project.properties res src
生成javah文件
$ javah -classpath bin/classes -d jni com.skywang.ndk.Myndk
-classpath:后面接“類的路徑”。
-d : 后面接“生成的頭文件存放的目錄”,d表示destination。
com.example.hellojni.HelloJni:是完整類名。
上訴命令生成的的.h文件路徑:jni/com_skywang_ndk_Myndk.h
生成文件內容:

1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class com_skywang_ndk_Myndk */ 4 5 #ifndef _Included_com_skywang_ndk_Myndk 6 #define _Included_com_skywang_ndk_Myndk 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: com_skywang_ndk_Myndk 12 * Method: HelloNdk 13 * Signature: ()Ljava/lang/String; 14 */ 15 JNIEXPORT jstring JNICALL Java_com_skywang_ndk_Myndk_HelloNdk 16 (JNIEnv *, jobject); 17 18 #ifdef __cplusplus 19 } 20 #endif 21 #endif
補充:若執行javah命令時,遇到如下錯誤。是因為-classpath后面所接的路徑不對!
error: cannot access com.skywang.ndk.Myndk
class file for com.skywang.ndk.Myndk not found
javadoc: error - Class com.skywang.ndk.Myndk not found.
Error: No classes were specified on the command line. Try -help.
有了com_skywang_ndk_Myndk.h頭文件之后,我們就可以實現該頭文件中聲明的函數。
4 實現頭文件中聲明的函數
新建文件jni/hello_jni.c。hello_jni.c的代碼如下:
#include <string.h> #include <jni.h> JNIEXPORT jstring JNICALL Java_com_skywang_ndk_Myndk_HelloNdk (JNIEnv* env, jobject obj) { return (*env)->NewStringUTF(env, "Hello JNI!"); }
hello_jni.c的作用就是實現com_skywang_ndk_Myndk.h中聲明的函數。
5 編寫實現函數對應的Android.mk
添加文件jni/Android.mk,內容如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello_jni LOCAL_SRC_FILES := hello_jni.c include $(BUILD_SHARED_LIBRARY)
6 編譯生成庫文件
進入到工程所在目錄,執行ndk-build,編譯生成.so庫文件。
$ cd /home/skywang/workspace/ndk/myndk/
$ ndk-build
生成庫文件所在目錄:libs/armeabi/libhello_jni.so
7 重新運行工程
重新運行eclipse下的myndk工程。輸出如下: