Android中關於JNI 的學習(零)簡單的例子,簡單地入門

來源:互聯網
上載者:User

標籤:android   ndk   jni   anrdoid.mk   例子   

Android中JNI的作用,就是讓Java能夠去調用由C/C++實現的代碼,為了實現這個功能,需要用到Anrdoid提供的NDK工具包,在這裡不講如何配置了,好麻煩,配置了好久。。。

本質上,Java去調用C/C++的代碼其實就是去調用C/C++提供的方法,所以,第一步,我們要建立一個類,並且定義一個Native方法,如下:

JniTest類:

public class JniTest {public native String getTestString();}

可以看到,在這個方法的前面,用到了native關鍵字。

接著,我們要在命令列中編譯這個java檔案,得到一個class檔案,如下:


然後我們可以利用javah命令檔案,產生一個C的標頭檔,其實javah這一步不是必需的,因為建立這個標頭檔,只是為了方便我們複製這個Jni中對應的方法名稱,因為這些名稱實在太複雜了。 

在這裡有一點要注意,javah命令要在包的根目錄下調用,對應的類檔案,必須是完整的類名,如所示,會先回到src目錄,再調用javah命令。

這樣我們就會在src檔案夾下在產生一個標頭檔,如所示:


我們可以看到其名稱是com_lms_jni_JniTest.h,其實就是包名+類名,我們可以看看裡面的內容:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_lms_jni_JniTest */#ifndef _Included_com_lms_jni_JniTest#define _Included_com_lms_jni_JniTest#ifdef __cplusplusextern "C" {#endif/* * Class:     com_lms_jni_JniTest * Method:    getTestString * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_lms_jni_JniTest_getTestString  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

我們可以看到,在這裡面有一個方法,名稱是Java_com_lms_jni_JniTest_getTestString,夠複雜吧,其實如果我們知道這個名稱規則,並且知道如何去實現這樣一個方法的話,我們是完全可以不產生這個標頭檔的,我們可以直接寫出對應的C檔案。

接下來,在jni檔案中建立一個對應的C檔案,名稱是值得並無所謂,但為了統一,我們就把它叫JniTest.c吧,如下:


在這裡,我們也把com_lms_jni_JniTest.h也放到這裡了,這個其實是沒關係的,只是為了內容的協調和統一而已,一般情況下,我們會把所以由C/C++實現的檔案都放在項目目錄下一個叫 jni 的檔案夾下面。

下面是在JniTest.c中實現native方法,getTestString,如下:

#include <stdio.h>#include <stdlib.h>#include <jni.h>JNIEXPORT jstring JNICALL Java_com_lms_jni_JniTest_getTestString  (JNIEnv *e, jobject obj){return (**e).NewStringUTF(e,"Hello from JniTest Function");}

在這個c檔案中,我們看到,並沒有引用標頭檔com_lms_jni_JniTest.h,而只是引用了一般的C/C++庫檔案,比如stido.h和stdlib.h檔案等,在這裡注意到一點,我們還會引用jni.h檔案,jni.h檔案是JNI編程中很重要的一個標頭檔,關於Java中的資料類型跟jni中的資料類型的對應全部是在這個檔案中定義的,後續會來看一下這個jni.h檔案。

在上面JniTest.c檔案中實現了方法之後,關於C/C++這邊的實現其實也就實現了,那麼接下來就是要將這個C檔案編譯成so檔案由Android來調用。

為什麼是so檔案呢,這是因為Android本質上就是一個linux系統,所以其調用的JNI庫檔案,都是so形式。

Android提供的NDK庫提供了ndk-build的命令來實現這個編譯過程,但在此之前,我們要先建立一個Android.mk檔案,這是一個簡單的小小的Make檔案,其內容如下:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := com_lms_jni_HwDemoLOCAL_SRC_FILES := HwDemo.c JniTest.c include $(BUILD_SHARED_LIBRARY)

在這裡,我們會定義幾個變數:

LOCAL_PATH:其值是call my-dir,而my-dir是個宏函數,會返回Android.mk所在的路徑,在這裡,就是jni檔案夾。

include $(CLEAR_VARS),這個命令會清除掉所有LOCAL開頭的變數,比如LOCAL_MODULE之類的,但有一個例外,就是其上面的LOCAL_PATH 。

LOCAL_MODULE:要產生的so包名,也是Android中Java代碼載入時的名稱。

LOCAL_SRC_FILES:要進行編譯的源檔案,如在這裡,有HwDemo.c和JniTest.c等。

include $(BUILD_SHARED_LIBRARY):表明產生一個動態連結程式庫。

定義後這樣一個Android.mk檔案之後,在命令列中調用ndk-build命令,如下:


命令實行之後,我們可以在項目目錄下看到libs中多了一個so庫,如下:


到這裡,關於Jni實現的就結束了,接下來就是如何在Android中使用這個本地方法了。

我們建立了一個Activity,在它裡面只放置一個TextView控制項,它的布局如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/tvJni"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="test" /></LinearLayout>

然後在Activity中,我們要載入這個so庫,如下:

public class HwDemo extends Activity {static {System.loadLibrary("com_lms_jni_HwDemo");//載入so庫}public native String printHello();@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);TextView tv = (TextView)findViewById(R.id.tvJni);JniTest jniTest = new JniTest();//調用JniTest檔案的方法tv.setText(jniTest.getTestString());}}

1)利用static靜態代碼塊,載入so庫檔案,可以看到在這裡,這個名稱就是Anrdoid.mk中定義的LOCAL_MODULE值。

2)建立JniTest對象,調用其getTestString()方法,最終顯示結果如下:


到這裡,通過一個簡單的例子,我們明白了如何在Android中利用JNI來調用C/C++的方法了。

最後,我們總結一下這幾個步驟:

1)建立Java類檔案,並定義Native方法,如JniTest類。

2)利用javac產生class檔案,然後回到src目錄,利用javah產生C/C++標頭檔,在這裡要注意,javah命令要在包的根目錄下調用,對應的類檔案,必須是完整的類名,如下:

在Src目錄:javah com.lms.jni.JniTest,在上面的,也可以看到javac之後,是回到src目錄,再調用javah。

3)編寫對應的C檔案,如JniTest.c,在裡面實現C/C++的方法,記得要放在jni檔案夾下面。

4)編寫Android.mk檔案,利用ndk-build命令產生so檔案。

5)在Android中利用static靜態代碼塊,調用system.loadLibrary方法來載入so庫檔案。

6)在Java邏輯中調用之前定義的JniTest類的方法。

結束。原始碼下載!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.