Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android學習——第一個NDK程序

Android學習——第一個NDK程序

編輯:關於Android編程

  在前面的學習中,我們已經講解了關於NDK編程的環境搭建流程,簡單的使用我們也通過官網本身自帶的例子進行說明了。可是相信大家一定還存在這麼的一個疑惑:“如果我要自己利用NDK編寫一個Android應用,具體應該怎麼做?有什麼要求”。OK,別擔心,下面就讓我們一起來利用NDK來編寫一個簡單的Android應用。   1 創建一個新的Project    1) 通過以下命令創建一個新的Android Project (詳細的使用方法,大家可以回去重新參考博文《Android學習第二天-android常用命令》)   android create project -n myfirstndk -t 1 -p ./myfirstndk -k cn.uc.myjni -a MainActivity  當Project創建成功後,我們可以通過查看文件夾發現它的大體架構如下圖:        2 開始Coding    1) 進入該項目的MainActivity.java所在的目錄下,新建一個定義本地方法的類 NumberSum.java ,輸入以下代碼:      1 package cn.uc.myjni;  2   3 public class NumberSum {  4   5     // 聲明一個本地方法  6     public native int add (int a, int b);  7   8     // 加載名為 libnumber_sum.so的庫  9     // 根據Unix的規則,系統為自動為number_sum 10     // 添加上lib前綴和.so後綴 11     static { 12         System.loadLibrary("number_sum"); 13     } 14 }          2) 調用以下命令,編譯NumberSum.java   javac -encoding UTF-8 NumberSum.java 編譯成功後,控制台並沒有特別的輸出,同時,我們可以在目錄下發現Number.class文件        這裡需要注意的是,我的命令中之所以指定源文件使用的編碼是因為我使用的是UTF-8編碼,在windows中直接通過javac NumberSum.java 進行編譯的話,會出現以下錯誤:              3) 返回項目源代碼文件夾下,比如我的就是返回到src目錄下,通過javah命令,生成頭文件:   javah cn.uc.myjni.NumberSum 執行成功後,控制台沒有輸出什麼特別的內容,同時,我們可以發現在src目錄下多了一個頭文件:           javah生成的頭文件知識講解:     ① 從頭文件的名字我們可以看出,它是由編譯的調用本地方法的類名及其所在的包名通過下劃線"_"分割組成。如我們的程序中是編譯cn.uc.myjni.NumberSum生成的,所以就算cn_uc_myjni_NumberSum     ② 頭文件中的內容可能很多,但是我們只關注這個方法的聲明:   JNIEXPORT jint JNICALL Java_cn_uc_myjni_NumberSum_add  (JNIEnv *, jobject, jint, jint);   在這個聲明中,我們可以清晰的看到方法名的最後面add就是在NumberSum類中聲明的本地方法add,而前面的是 cn_uc_myjni_NumberSum就算完整的包名和類名,由此我們可以知道,一個完整的JNI函數名有3部分組成:Java、定義native方法的類的全名(包名+類名)、實際的函數名。這三部分用"_"進行連接。          4) 在Project的根目錄下,新建一個文件夾jni (必須叫做jni),將我們之前生成的頭文件移動到jni文件夾下,如圖:                5) 新建一個c文件,名字為 number_sum.c,輸入以下代碼:     1 #include <jni.h>   2  3 // 此處的方法簽名與頭文件中聲明的方法簽名是相同的 4 // 建議直接從頭文件中復制過來  5 JNIEXPORT jint JNICALL Java_cn_uc_myjni_NumberSum_add(JNIEnv *env,jobject obj,jint a,jint b)   6 {   7     return (a+b);   8 }       下面講解下上面的一些相關內容:     ① JNIEXPORT jint JNICALL JNIEnv 等都是在jni.h中定義的;     ② 其中上面參數中的env表示JNI的調用環境,obj表示定義native方法的Java類的對象本身。         6) 新建一個Android.mk 文件,建議直接從官方文檔給的例子 hello-jni 中復制出來進行修改LOCAL_MODUE 和 LOCAL_SRC_FILES,代碼如下:   LOCAL_PATH := $(call my-dir)   include $(CLEAR_VARS)   LOCAL_MODULE    := number_sum LOCAL_SRC_FILES := number_sum.c   include $(BUILD_SHARED_LIBRARY)      下面我們簡單講解一下上面幾個參數的含義吧:     ① LOCAL_PATH:Android.mk 的第一行必須是LOCAL。用於指定參與編譯的C/C++源文件的位置。在上面例子中,宏函數mydir 是由系統提供的,用來返回當前目錄的路徑。也就是包含Android.mk文件的目錄的路徑。     ② include ${CLEAR_VARS}:CLEAR_VARS變量是在系統中定義的,用來指定一個特殊的GNU Make文件。該文件用來清空很多以LOCAL_開頭的變量,例如LOCAL_MODULE、LOCAL_SRC_FILES、LOCAL_STATIC_LIBRARIES 等。但這些變量不包括LOCAL_PATH。之所以要清空這些變量,是因為這些都是全局變啦ing。同時這些變量又要在不同的GNU Make文件中使用,為了多個GNU Make文件不相互影響,就需要在執行每一個GNU make文件(Android.mk文件)之前先清空這些變量。     ③ LOCAL_MODULE := number_sum :在每一個模塊中必須定義 LOCAL_MODULE變量,用來指定生成的模塊名。該變量的值必須是唯一的,而且不能包含任何空白分隔符。實際上,LOCAL_MODULE 變量的值就是生產共享庫的文件名(不包括lib和.so),在編譯時,系統會自動在文件名的前後添加上lib 和.so 。如果該模塊名前綴加了lib,在生產共享庫的時候不會進行添加。     ④ LOCAL_SRC_FILES := number_sum.c:用來指定一個C/C++源文件列表,這裡不需要指定頭文件,系統會自動計算當前C/C++源文件 include的頭文件。系統就直接將LOCAL_SRC_FILES變量指定的源文件傳給編譯器。C++源文件的默認擴展名是.cpp,但可以通過LOCAL_DEFAULT_CPP_EXTENSION 變量改變 C++文件默認拓展名,例如將該變量的值設成".cxx",注意不要忘記了" . "     ⑤ include ${BUILD_SHARED_LIBRARY} : BUILD_SHARED_LIBRARY是在系統中定義的,用來指定一個GNU Make腳本文件。該腳本文件會根據以LOCAL_開頭的變量來生成共享庫文件。如果想生成靜態庫文件,可以使用BUILD_STATIC_LIBRARY變量。          7) 為了能夠把我們調用共享代碼庫執行的程序結果顯示出來,我們對生成的代碼界面進行一定的修改:        I. 打開 res/layout/main.xml 文件,給TextView添加上一個Id,方便我們在後台通過id獲取組件進行顯示內容的修改:      1 <?xml version="1.0" encoding="utf-8"?>  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  3     android:orientation="vertical"  4     android:layout_width="fill_parent"  5     android:layout_height="fill_parent"  6     >  7 <!-- 給TextView 添加了ID -->  8 <TextView    9     android:id="@+id/info_text" 10     android:layout_width="fill_parent"  11     android:layout_height="wrap_content"  12     android:text="Hello World, MainActivity" 13     /> 14 </LinearLayout>       II. 給我們的主界面MainActivity.java的onCreate() 方法添加上將結果顯示到界面上的邏輯代碼:      1 package cn.uc.myjni;  2   3 import android.app.Activity;  4 import android.widget.TextView;  5 import android.os.Bundle;  6   7 public class MainActivity extends Activity  8 {  9     /** Called when the activity is first created. */ 10     @Override 11     public void onCreate(Bundle savedInstanceState) 12     { 13         super.onCreate(savedInstanceState); 14         setContentView(R.layout.main); 15  16         // 通過Id獲取TextView組件 17         TextView textView=(TextView) findViewById(R.id.info_text);   18         NumberSum sum = new NumberSum();   19         // 調用本地方法  20         int result=sum.add(10, 20);   21         textView.append("\n 10+20="+result);  22     } 23 }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved