1. JNI簡介
java
Java Native Interface (JNI)標準是Java平臺的一部分,它容許Java代碼和其餘語言寫的代碼進行交互。JNI 是本地編程接口。JVM封裝了各類操做系統實際的差別性的同時,提供了JNI技術,使得開發者能夠經過程序調用到操做系統相關的技術實現的庫函數,從而與其餘技術和系統交互,使用其餘技術實現的系統的功能,同時其餘技術和系統也能夠用過JNI的相應原生接口調用Java應用系統內部實現的功能。c++
2. 爲何要使用JNI編程
Java程序中調用C/C++開發的共享庫,主要爲了提升程序效率,固然程序的可移植性。好比如今公司要開發一款地圖引擎,要求實現Android,IOS,JS等多平臺移植,那麼就要使用C++去開發地圖引擎核心,去讓那些平臺調用,實現相應的產品。對於Android來講,就要經過JNI來調用這個引擎核心,而IOS自己就支持C/C++。eclipse
3. JNI實例ide
(1) 編寫Android項目,項目包名爲:com.h1024.hellojni函數
程序入口:MainActivitythis
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = (TextView) findViewById(R.id.tv); TestNDK ndk = new TestNDK(); tv.setText(ndk.sayHello()+" ////1+2= "+ndk.add(1, 2)); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
封裝本地接口方法:TestNDKspa
public class TestNDK { public native int add(int x,int y); public native String sayHello(); static { System.loadLibrary("TestNDK"); } }
最後運行項目,也就是將類編譯字節碼。
操作系統
(2) 添加本地支持,生成so庫等文件code
右擊工程,選擇Android Tools->Add Native Support,Library Name中寫上上面要加載的庫文件(TestNDK),結果在本地生成jni,obj等文件夾還有一些包含庫的頭文件等。jni下面有TestNDK.cpp和Android.mk文件。下面是Android.mk文件的內容:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := TestNDK LOCAL_SRC_FILES := TestNDK.cpp include $(BUILD_SHARED_LIBRARY)
簡單說明一下,TestNDK就是要生成的so庫文件的名稱,而TestNDK.cpp則是c++代碼的實現,其餘的不須要管,詳細狀況請本身查閱資料。
要想生成支持各中硬件的so庫,則需本身新建一個文件,名字固定叫Application.mk,其內容是:
APP_ABI := all
運行項目(eclipse中設置ndk,自動編譯),也就是編譯後結果是在libs文件下生成armeabi,armeabi-v7a,mips,x86文件夾,各個文件下的都有對應的so庫文件。
(3) 使用javah生成C++頭文件
打開終端,cd進入工程目錄,而後輸入javah -classpath bin/classes -d jni com.h1024.hellojni.TestNDK,回車,在eclipse中刷新項目,就會看到jni文件裏多了一個.h文件,重命名爲TestNDK.h。其內容是:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_h1024_hellojni_TestNDK */ #ifndef _Included_com_h1024_hellojni_TestNDK #define _Included_com_h1024_hellojni_TestNDK #ifdef __cplusplus extern "C" { #endif /* * Class: com_h1024_hellojni_TestNDK * Method: add * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_h1024_hellojni_TestNDK_add (JNIEnv *, jobject, jint, jint); /* * Class: com_h1024_hellojni_TestNDK * Method: sayHello * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_h1024_hellojni_TestNDK_sayHello (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
在TestNDK.cpp文件中實現頭文件裏方法。
#include "TestNDK.h" #include <string.h> JNIEXPORT jint JNICALL Java_com_h1024_hellojni_TestNDK_add (JNIEnv * env, jobject clazz, jint a, jint b){ return a+b; } JNIEXPORT jstring JNICALL Java_com_h1024_hellojni_TestNDK_sayHello (JNIEnv * env, jobject clazz){ return (env)->NewStringUTF("Hello from JNI!"); }
(4) 從新運行項目,生成最終的so庫。