Android與JNI(一)

 

返回主頁

Eddy_He

隨筆- 55  文章- 0  評論- 3 git

Android與JNI(一)

Android與JNI(一)web

 

軟件版本:
  ubuntu10.04
  java version "1.6.0_30-ea"
  eclipse
  android-ndk-r5bshell

目錄:express

  1. JNI 開發的基本步驟
  2. 建立一個 android 工程
  3. 生成 jni 的頭文件
  4. 編寫 c/c++ 代碼
  5. 編譯生成動態庫
  6. 測試
  7. 參考資料

1. JNI 開發的基本步驟

  在 JAVA 程序中調用 c/c++ 函數的方法通常是:

  一、建立一個類(HelloWorld.java)或者在原來的類中聲明本地方法。
  二、使用 javac 編譯源文件 HollowWorld.java,生成 HelloWorld.class。
  三、使用 javah –jni 來生成頭文件(HelloWorld.h),這個頭文件裏面包含了本地方法的函數原型。
  四、編寫 c/c++ 代碼(HelloWorld.c)實現頭文件中的函數原型。
  五、將 HelloWorld.c 編譯成一個動態庫,生成 Hello-World.dll 或者 libHello-World.so。
  六、使用 java 命令運行 HelloWorld 程序,類文件 HelloWorld.class 和本地庫(HelloWorld.dll 或者 libHelloWorld.so)在運行時被加載。

  如圖所示:

2. 建立一個 android 工程

  建立一個新的 android 工程 HelloJNI 便於演示:

複製代碼

 1 package com.example.hellojni; 2  3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.view.Menu; 6 import android.view.MenuItem; 7 import android.widget.TextView; 8 import android.support.v4.app.NavUtils; 9 10 public class HelloJNI extends Activity {11 12     @Override13     public void onCreate(Bundle savedInstanceState) {14         super.onCreate(savedInstanceState);15         setContentView(R.layout.hello_jni);16         getActionBar().setDisplayHomeAsUpEnabled(true);17         18         /* Create a TextView and set its content.19          * the text is retrieved by calling a native20          * function.21          */22         TextView  tv = new TextView(this);23         tv.setText( stringFromJNI() );24         setContentView(tv);25     }26 27     @Override28     public boolean onCreateOptionsMenu(Menu menu) {29         getMenuInflater().inflate(R.menu.hello_jni, menu);30         return true;31     }32 33     34     @Override35     public boolean onOptionsItemSelected(MenuItem item) {36         switch (item.getItemId()) {37             case android.R.id.home:38                 NavUtils.navigateUpFromSameTask(this);39                 return true;40         }41         return super.onOptionsItemSelected(item);42     }43 44     /* A native method that is implemented by the45      * 'HelloJNI' native library, which is packaged46      * with this application.47      */48     public native String  stringFromJNI();49 50     /* This is another native method declaration that is *not*51      * implemented by 'HelloJNI'. This is simply to show that52      * you can declare as many native methods in your Java code53      * as you want, their implementation is searched in the54      * currently loaded native libraries only the first time55      * you call them.56      *57      * Trying to call this function will result in a58      * java.lang.UnsatisfiedLinkError exception !59      */60     public native String  unimplementedStringFromJNI();61 62     /* this is used to load the 'HelloJNI' library on application63      * startup. The library has already been unpacked into64      * /data/data/com.example.HelloJni/lib/libHelloJNI.so at65      * installation time by the package manager.66      */67     static {68         System.loadLibrary("HelloJNI");69     }70 }

複製代碼

  代碼很簡單,主要是調用本地方法返回一個字符串,顯示在屏幕上。有兩點須要針對說明一下:

1 static {2         System.loadLibrary("HelloJNI");3 }

  上面這幾行代碼是用來加載動態庫 libHelloJNI.so 。那麼是在何時加載呢?當第一次使用到這個類的時候就會加載。

1 public native String stringFromJNI();2 public native String unimplementedStringFromJNI();

  使用關鍵字 native 聲明本地方法,代表這兩個函數須要經過本地代碼 c/c++ 實現。

  經過 eclipse 編譯代碼,生成 .class 文件。爲生成 jni 的頭文件作好準備。

3. 生成 jni 的頭文件 

  如今的問題是要怎麼樣實現 stringFromJNI 和 unimplementedStringFromJNI 這兩個函數呢?這兩個函數要怎麼命名?直接用這兩個名字行不行?要解決這些疑問,就要用到 javah 這個命令。

  在你新建成的工程根目錄下,鍵入如下命令:

$javah -classpath bin/classes -d jni com.example.hellojni.HelloJNI

  先簡單說一下這個命令有什麼用。這個命令是用來生成與指定 class 想對應的本地方法的頭文件。

  -classpath:指定類的路徑。
  -d:輸出目錄名。
  com.example.hellojni.HelloJNI:完整的類名。

  命令的結果是在本地生成一個名爲 jni 的目錄,裏面有一個名爲 com_example_hellojni_HelloJNI.h 的頭文件。這個文件就是咱們所須要的頭文件,他聲明瞭兩個函數

$lsAndroidManifest.xml  assets  bin  gen  ic_launcher-web.png  jni  libs  obj  proguard-project.txt  project.properties  res  src

複製代碼

 1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class com_example_hellojni_HelloJNI */ 4  5 #ifndef _Included_com_example_hellojni_HelloJNI 6 #define _Included_com_example_hellojni_HelloJNI 7 #ifdef __cplusplus 8 extern "C" { 9 #endif10 /*11  * Class:     com_example_hellojni_HelloJNI12  * Method:    stringFromJNI13  * Signature: ()Ljava/lang/String;14  */15 JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJNI_stringFromJNI16   (JNIEnv *, jobject);17 18 /*19  * Class:     com_example_hellojni_HelloJNI20  * Method:    unimplementedStringFromJNI21  * Signature: ()Ljava/lang/String;22  */23 JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJNI_unimplementedStringFromJNI24   (JNIEnv *, jobject);25 26 #ifdef __cplusplus27 }28 #endif29 #endif

複製代碼

  上面代碼中的 JNIEXPORT 和 JNICALL 是 jni 的宏,在 android 的 jni 中不須要,固然寫上去也不會有錯。

  函數名比較長,不過是有規律的,按照:java_pacakege_class_method 形式來命名。調用 stringFromJNI() 就會執行 JNICALL Java_com_example_hellojni_HelloJNI_stringFromJNI() 。

  還有一個地方須要注意一下,那就是第13行

  Signature: ()Ljava/lang/String;
  
()表示函數的參數爲空(這裏爲空是指除了JNIEnv *, jobject 這兩個參數以外沒有其餘參數,JNIEnv* 和 jobject 是全部 jni 函數必有的兩個參數,分別表示 jni 環境和對應的 java 類(或對象)自己);
  Ljava/lang/String; 表示函數的返回值是 java 的 String 對象。

4. 編寫 c/c++ 代碼

  按照 com_example_hellojni_HelloJNI.h 中聲明的函數名,在 jni 目錄下創建一個 HelloJNI.c 文件實現其函數體。

複製代碼

 1 /* 2  * Copyright (C) 2009 The Android Open Source Project 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); 5  * you may not use this file except in compliance with the License. 6  * You may obtain a copy of the License at 7  * 8  *      http://www.apache.org/licenses/LICENSE-2.0 9  *10  * Unless required by applicable law or agreed to in writing, software11  * distributed under the License is distributed on an "AS IS" BASIS,12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13  * See the License for the specific language governing permissions and14  * limitations under the License.15  *16  */17 #include <string.h>18 #include <jni.h>19 #include "com_example_hellojni_HelloJNI.h"20 21 /* This is a trivial JNI example where we use a native method22  * to return a new VM String. See the corresponding Java source23  * file located at:24  *25  *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java26  */27 jstring Java_com_example_hellojni_HelloJNI_stringFromJNI(JNIEnv *env, jobject this)28 {29     return (*env)->NewStringUTF(env, "Hello from JNI !");30 }

複製代碼

  這裏只實現了 Java_com_example_hellojni_HelloJNI_stringFromJNI() ,函數很簡單,返回一個字符串。可是因爲函數定義中的返回值是 java 的 String 類,因此不能簡單的返回一個字符串,須要經過 JNI 函數 NewStringUTF 在本地建立一個新的 java.lang.String 對象。這個新建立的字符串對象擁有一個與給定的 UTF-8 編碼的 C 類型字符串內容相同的 Unicode 編碼字符串。這裏拋出了一個問題,就是說咱們在寫 JNI 的時候,有些數據類型是須要作轉換的。

5. 編譯生成動態庫

  若是你尚未下載 ndk 的話,請到這裏來下載。ndk 有什麼用?就是用來編譯 jni 代碼的。安裝方法很簡單,只要把 ndk-build 命令加入到環境變量 PATH 中就可使用了。驗證方法就是鍵入 ndk-build 命令後,不會出現 command not found 的字樣。

  在 jni 目錄下建立一個名爲 Android.mk 的文件,並輸入如下內容:

複製代碼

 1 # Copyright (C) 2009 The Android Open Source Project 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 #      http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software10 # distributed under the License is distributed on an "AS IS" BASIS,11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12 # See the License for the specific language governing permissions and13 # limitations under the License.14 #15 LOCAL_PATH := $(call my-dir)16 17 include $(CLEAR_VARS)18 19 LOCAL_MODULE    := HelloJNI20 LOCAL_SRC_FILES := HelloJNI.c21 22 include $(BUILD_SHARED_LIBRARY)

複製代碼

  而後在 jni 目錄下輸入 ndk-build 命令就能夠編譯了。

$ndk-build 
Compile thumb  : HelloJNI <= HelloJNI.c
SharedLibrary  : libHelloJNI.so
Install        : libHelloJNI.so => libs/armeabi/libHelloJNI.so

  將會在 HelloJNI/libs/armeabi 目錄下生成一個名爲 libHelloJNI.so 的動態庫。編譯生成 apk 時會把這個庫一塊兒打包。

6. 測試

  7. 參考資料

  [1]. Android: NDK編程入門筆記
  [2]. JNI及Android JNI 開發基本知識和具體操做步驟
  [3]. 如何在Android下使用JNI

分類: Android

標籤: android, jni

綠色通道: 好文要頂 關注我 收藏該文與我聯繫

Eddy_He
關注 - 7
粉絲 - 2

+加關注

0

0

(請您對文章作出評價)

« 上一篇:推理題-爸爸的生日-答案分析
» 下一篇:Android與JNI(二)

posted @ 2012-08-08 17:23 Eddy_He 閱讀(1759) 評論(0) 編輯 收藏

 

刷新評論刷新頁面返回頂部

註冊用戶登陸後才能發表評論,請 登陸註冊訪問網站首頁。

【推薦】50萬行VC++源碼: 大型組態工控、電力仿真CAD與GIS源碼庫
融雲,免費爲你的App加入IM功能——讓你的App「聊」起來!!

<DIV style="BORDER-BOTTOM: 0pt; BORDER-LEFT: 0pt; BORDER-TOP: 0pt; BORDER-RIGHT: 0pt" id=google_ads_iframe_/1090369/cnblogs_blogpost_C1_sitehome_0__container__ name="google_ads_iframe_/1090369/cnblogs_blogpost_C1_sitehome_0__container__"><IFRAME style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; VERTICAL-ALIGN: bottom; BORDER-TOP: 0px; BORDER-RIGHT: 0px" id=google_ads_iframe_/1090369/cnblogs_blogpost_C1_sitehome_0 height=250 marginHeight=0 src="javascript:""" frameBorder=0 width=300 allowTransparency name=google_ads_iframe_/1090369/cnblogs_blogpost_C1_sitehome_0 marginWidth=0 scrolling=no>

最新IT新聞:
· 馮侖:創業就是失去如今要將來
· Chrome 42發佈,向用戶推送通知和禁用Java
· iOS開發者:蘋果你深深的傷害了我,還不讓我說
· 最低499元iPhone官翻不給中低端安卓活路
· 調查顯示:微軟比蘋果更具社會責任感
» 更多新聞...

<DIV style="BORDER-BOTTOM: 0pt; BORDER-LEFT: 0pt; BORDER-TOP: 0pt; BORDER-RIGHT: 0pt" id=google_ads_iframe_/1090369/cnblogs_blogpost_C2_0__container__ name="google_ads_iframe_/1090369/cnblogs_blogpost_C2_0__container__"><IFRAME style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; VERTICAL-ALIGN: bottom; BORDER-TOP: 0px; BORDER-RIGHT: 0px" id=google_ads_iframe_/1090369/cnblogs_blogpost_C2_0 height=60 marginHeight=0 src="javascript:""" frameBorder=0 width=468 allowTransparency name=google_ads_iframe_/1090369/cnblogs_blogpost_C2_0 marginWidth=0 scrolling=no>

最新知識庫文章:

· 談「測試驅動的開發」
· 好團隊不可能憑空出現,贏在Leader的可行規劃
· 移動應用測試——打造完美應用的祕訣
· 什麼是對象,爲何要面向對象,怎麼才能面向對象?
· 驅動方法不能改變任何事情

» 更多知識庫文章...

公告

暱稱:Eddy_He
園齡:3年1個月
粉絲:2
關注:7

+加關注

< 2012年8月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

搜索

 

 

經常使用連接

    個人標籤

    隨筆分類

    隨筆檔案

    文章分類

    最新評論

    閱讀排行榜

    評論排行榜

    推薦排行榜

    Copyright ©2015 Eddy_He

    相關文章
    相關標籤/搜索