欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android NDK開(kāi)發(fā)詳細(xì)介紹

 更新時(shí)間:2016年09月07日 11:53:16   作者:Devin Zhang  
本文主要介紹Android NDK開(kāi)發(fā),這里詳細(xì)整理了相關(guān)資料并介紹 NDK的知識(shí)和開(kāi)發(fā)流程及簡(jiǎn)單示例代碼,幫助大家學(xué)習(xí),有需要的小伙伴可以參考下

Android之NDK開(kāi)發(fā)

 一、NDK產(chǎn)生的背景

  Android平臺(tái)從誕生起,就已經(jīng)支持C、C++開(kāi)發(fā)。眾所周知,Android的SDK基于Java實(shí)現(xiàn),這意味著基于Android SDK進(jìn)行開(kāi)發(fā)的第三方應(yīng)用都必須使用Java語(yǔ)言。但這并不等同于“第三方應(yīng)用只能使用Java”。在Android SDK首次發(fā)布時(shí),Google就宣稱(chēng)其虛擬機(jī)Dalvik支持JNI編程方式,也就是第三方應(yīng)用完全可以通過(guò)JNI調(diào)用自己的C動(dòng)態(tài)庫(kù),即在Android平臺(tái)上,“Java+C”的編程方式是一直都可以實(shí)現(xiàn)的。

  不過(guò),Google也表示,使用原生SDK編程相比Dalvik虛擬機(jī)也有一些劣勢(shì),Android SDK文檔里,找不到任何JNI方面的幫助。即使第三方應(yīng)用開(kāi)發(fā)者使用JNI完成了自己的C動(dòng)態(tài)鏈接庫(kù)(so)開(kāi)發(fā),但是so如何和應(yīng)用程序一起打包成apk并發(fā)布?這里面也存在技術(shù)障礙。比如程序更加復(fù)雜,兼容性難以保障,無(wú)法訪問(wèn)Framework API,Debug難度更大等。開(kāi)發(fā)者需要自行斟酌使用。

  于是NDK就應(yīng)運(yùn)而生了。NDK全稱(chēng)是Native Development Kit。

  NDK的發(fā)布,使“Java+C”的開(kāi)發(fā)方式終于轉(zhuǎn)正,成為官方支持的開(kāi)發(fā)方式。NDK將是Android平臺(tái)支持C開(kāi)發(fā)的開(kāi)端。

二、為什么使用NDK

  1.代碼的保護(hù)。由于apk的java層代碼很容易被反編譯,而C/C++庫(kù)反匯難度較大。

  2.可以方便地使用現(xiàn)存的開(kāi)源庫(kù)。大部分現(xiàn)存的開(kāi)源庫(kù)都是用C/C++代碼編寫(xiě)的。

  3.提高程序的執(zhí)行效率。將要求高性能的應(yīng)用邏輯使用C開(kāi)發(fā),從而提高應(yīng)用程序的執(zhí)行效率。

  4.便于移植。用C/C++寫(xiě)得庫(kù)可以方便在其他的嵌入式平臺(tái)上再次使用。

三、NDK簡(jiǎn)介

       1.NDK是一系列工具的集合

       NDK提供了一系列的工具,幫助開(kāi)發(fā)者快速開(kāi)發(fā)C(或C++)的動(dòng)態(tài)庫(kù),并能自動(dòng)將so和java應(yīng)用一起打包成apk。這些工具對(duì)開(kāi)發(fā)者的幫助是巨大的。

NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU、平臺(tái)、ABI等差異,開(kāi)發(fā)人員只需要簡(jiǎn)單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創(chuàng)建出so。

NDK可以自動(dòng)地將so和Java應(yīng)用一起打包,極大地減輕了開(kāi)發(fā)人員的打包工作。

       2.NDK提供了一份穩(wěn)定、功能有限的API頭文件聲明

       Google明確聲明該API是穩(wěn)定的,在后續(xù)所有版本中都穩(wěn)定支持當(dāng)前發(fā)布的API。從該版本的NDK中看出,這些API支持的功能非常有限,包含有:C標(biāo)準(zhǔn)庫(kù)(libc)、標(biāo)準(zhǔn)數(shù)學(xué)庫(kù)(libm)、壓縮庫(kù)(libz)、Log庫(kù)(liblog)。

四、NDK開(kāi)發(fā)環(huán)境的搭建

1.下載安裝Android NDK

  地址:http://developer.android.com/sdk/ndk/index.html

2.下載安裝cygwin

  由于NDK編譯代碼時(shí)必須要用到make和gcc,所以你必須先搭建一個(gè)linux環(huán)境, cygwin是一個(gè)在windows平臺(tái)上運(yùn)行的unix模擬環(huán)境,它對(duì)于學(xué)習(xí)unix/linux操作環(huán)境,或者從unix到windows的應(yīng)用程序移植,非常有用。通過(guò)它,你就可以在不安裝linux的情況下使用NDK來(lái)編譯C、C++代碼了。下載地址:http://www.cygwin.com

  1)然后雙擊運(yùn)行吧,運(yùn)行后你將看到安裝向?qū)Ы缑妗?/p>

  2)點(diǎn)擊下一步,此時(shí)讓你選擇安裝方式:

Install from Internet:直接從Internet上下載并立即安裝(安裝完成后,下載好的安裝文件并不會(huì)被刪除,而是仍然被保留,以便下次再安裝)。
Download Without Installing:只是將安裝文件下載到本地,但暫時(shí)不安裝。
Install from Local Directory:不下載安裝文件,直接從本地某個(gè)含有安裝文件的目錄進(jìn)行安裝。

  3)選擇第一項(xiàng),然后點(diǎn)擊下一步。

  4)選擇要安裝的目錄,注意,最好不要放到有中文和空格的目錄里,似乎會(huì)造成安裝出問(wèn)題,其它選項(xiàng)不用變,之后點(diǎn)下一步:

  5)上一步是選擇安裝cygwin的目錄,這個(gè)是選擇你下載的安裝包所在的目錄,默認(rèn)是你運(yùn)行setup.exe的目錄,直接點(diǎn)下一步就可以:

  6)此時(shí)你共有三種連接方式選擇:

Direct Connection:直接連接。
Use IE5 Settings:使用IE的連接參數(shù)設(shè)置進(jìn)行連接。
Use HTTP/FTP Proxy:使用HTTP或FTP代理服務(wù)器進(jìn)行連接(需要輸入服務(wù)器地址、端口號(hào))。

  用戶可根據(jù)自己的網(wǎng)絡(luò)連接的實(shí)情情況進(jìn)行選擇,一般正常情況下,均選擇第一種,也就是直接連接方式。然后再點(diǎn)擊“下一步”。

  7)這是選擇要下載的站點(diǎn),選擇后點(diǎn)下一步。

  8)此時(shí)會(huì)下載加載安裝包列表

  9)Search是可以輸入你要下載的包的名稱(chēng),能夠快速篩選出你要下載的包。那四個(gè)單選按鈕是選擇下邊樹(shù)的樣式,默認(rèn)就行,不用動(dòng)。View默認(rèn)是Category,建議改成full顯示全部包再查,省的一些包被隱藏掉。左下角那個(gè)復(fù)選框是是否隱藏過(guò)期包,默認(rèn)打鉤,不用管它就行,下邊開(kāi)始下載我們要安裝的包吧,為了避免全部下載,這里列出了后面開(kāi)發(fā)NDK用得著的包:autoconf2.1、automake1.10、binutils、gcc-core、gcc- g++、gcc4-core、gcc4-g++、gdb、pcre、pcre-devel、gawk、make共12個(gè)包

  10)然后開(kāi)始選擇安裝這些包吧,點(diǎn)skip,把它變成數(shù)字版本格式,要確保Bin項(xiàng)變成叉號(hào),而Src項(xiàng)是源碼,這個(gè)就沒(méi)必要選了。

  11)下面測(cè)試一下cygwin是不是已經(jīng)安裝好了。

      運(yùn)行cygwin,在彈出的命令行窗口輸入:cygcheck -c cygwin命令,會(huì)打印出當(dāng)前cygwin的版本和運(yùn)行狀 態(tài),如果status是ok的話,則cygwin運(yùn)行正常。

      然后依次輸入gcc –version,g++ --version,make –version,gdb –version進(jìn)行測(cè)試,如果都打印出版本信息和一些描述信息,則cygwin安裝成功!

3.配置 NDK 環(huán)境變量

  a.首先找到 cygwin 的安裝目錄,找到一個(gè) home\< 你的用戶名 >\.bash_profile 文件,我的是:E:\cygwin\home\Administrator\.bash_profile , ( 注意:我安裝的時(shí)候我的 home 文件夾下面什么都沒(méi)有,解決 的辦法:首先打開(kāi)環(huán)境變量,把里面的用戶變量中的 HOME 變量刪掉,在 E:\cygwin\home 文件夾下建立名為Administrator 的文件夾(是用戶名),然后把 E:\cygwin\etc\skel\.bash_profile 拷貝到該文件夾下 ) 。

  b.打開(kāi) bash_profile 文件,添加 NDK=/cygdrive/< 你的盤(pán)符 >/<android ndk 目錄 > 例如:

      NDK=/cygdrive/e/android-ndk-r5

      export NDK

  NDK 這個(gè)名字是隨便取的,為了方面以后使用方便,選個(gè)簡(jiǎn)短的名字,然后保存

  c.打開(kāi) cygwin ,輸入 cd $NDK ,如果輸出上面配置的 /cygdrive/e/android-ndk-r5 信息,則表明環(huán)境變量設(shè)置成功了。

4.用 NDK 來(lái)編譯程序  

  a.現(xiàn)在我們用安裝好的 NDK 來(lái)編譯一個(gè)簡(jiǎn)單的程序吧,我們選擇 ndk 自帶的例子 hello-jni ,我的位于E:\android-ndk-r5\samples\hello-jni( 根據(jù)你具體的安裝位置而定 ) ,

  b.運(yùn)行 cygwin ,輸入命令 cd /cygdrive/e/android-ndk-r5/samples/hello-jni ,進(jìn)入到 E:\android-ndk-r5\samples\hello-jni 目錄。

  c.輸入 $NDK/ndk-build ,執(zhí)行成功后,它會(huì)自動(dòng)生成一個(gè) libs 目錄,把編譯生成的 .so 文件放在里面。 ($NDK是調(diào)用我們之前配置好的環(huán)境變量, ndk-build 是調(diào)用 ndk 的編譯程序 )

  d.此時(shí)去 hello-jni 的 libs 目錄下看有沒(méi)有生成的 .so 文件,如果有,你的 ndk 就運(yùn)行正常啦!

5.在 eclipse 中集成 c/c++ 開(kāi)發(fā)環(huán)境

  a.裝 Eclipse 的 C/C++ 環(huán)境插件: CDT ,這里選擇在線安裝。  首先登錄 http://www.eclipse.org/cdt/downloads.php ,找到對(duì)應(yīng)你 Eclipse 版本的 CDT 插件 的在線安裝地址。

  b.然后點(diǎn) Help 菜單,找到 Install New Software 菜單

  c.點(diǎn)擊 Add 按鈕,把取的地址填進(jìn)去,出來(lái)插件列表后,選 Select All ,然后選擇下一步即可完成安裝。

  d.安裝完成后,在 eclispe 中右擊新建一個(gè)項(xiàng)目,如果出現(xiàn)了 c/c++ 項(xiàng)目,則表明你的 CDT 插件安裝成功啦!

6.配置 C/C++ 的編譯器

  a.打開(kāi) eclipse ,導(dǎo)入ndk 自帶的hello-jni 例子,右鍵單擊項(xiàng)目名稱(chēng),點(diǎn)擊 Properties ,彈出配置界面,之后再點(diǎn)擊 Builders ,彈出項(xiàng)目的編譯工具列表,之后點(diǎn)擊 New,新添加一個(gè)編譯器,點(diǎn)擊后出現(xiàn)添加界面,選擇 Program ,點(diǎn)擊 OK。

  b.出現(xiàn)了添加界面,首先給編譯配置起個(gè)名字,如: C_Builder,設(shè)置 Location 為 < 你 cygwin 安裝路徑 >\bin\bash.exe 程序,例:E:\cygwin\bin\bash.exe ,設(shè)置Working Directory為<你 cygwin 安裝路徑 >\bin 目錄,例如: E:\cygwin\bin,設(shè)置 Arguments 為 --login -c "cd /cygdrive/e/android-ndk-r5/samples/hello-jni && $NDK /ndk-build"

  上面的配置中 /cygdrive/e/android-ndk-r5/samples/hello-jni 是你當(dāng)前要編譯的程序的目錄, $NDK 是之前配置  的 ndk 的環(huán)境變量,這兩個(gè)根據(jù)你具體的安裝目錄進(jìn)行配置,其他的不用變, Arguments 這串參數(shù)實(shí)際是  給 bash.exe 命令行程序傳參數(shù),進(jìn)入要編譯的程序目錄,然后運(yùn)行 ndk-build 編譯程序

  c.接著切換到 Refresh 選項(xiàng)卡,給 Refresh resources upon completion 打上鉤

  d.然后切換到 Build Options 選項(xiàng)卡,勾選上最后三項(xiàng)

  e.之后點(diǎn)擊 Specify Resources 按鈕,選擇資源目錄,勾選你的項(xiàng)目目錄即可

  f.最后點(diǎn)擊 Finish,點(diǎn)擊 OK 一路把剛才的配置都保存下來(lái),注意:如果你配置的編譯器在其它編譯器下邊,記得一定要點(diǎn) Up 按鈕,把它排到第一位,否則 C 代碼的編譯晚于Java代碼的編譯,會(huì)造成你的 C 代碼要編譯兩次才能看到最新的修改。

  g.編譯配置也配置完成啦,現(xiàn)在來(lái)測(cè)試一下是否可以自動(dòng)編譯呢,打開(kāi)項(xiàng)目 jni 目錄里的 hello-jni.c 文件把提示 Hello from JNI! 改成其他的文字:如: Hello , My name is alex. ,然后再模 擬器中運(yùn)行你的程序,如果模擬器中顯示了你最新修改的文字,那么 Congratulations !你已經(jīng)全部配置成功啦!

五、開(kāi)發(fā)自己的NDK程序

  入門(mén)的最好辦法就是學(xué)習(xí)Android自帶的例子, 這里就通過(guò)學(xué)習(xí)Android的NDK自帶的demo程序:hello-jni來(lái)達(dá)到這個(gè)目的。

1、 開(kāi)發(fā)環(huán)境的搭建

  1)android的NDK開(kāi)發(fā)需要在linux下進(jìn)行: 因?yàn)樾枰袰/C++編寫(xiě)的代碼生成能在arm上運(yùn)行的.so文件,這就需要用到交叉編譯環(huán)境,而交叉編譯需要在linux系統(tǒng)下才能完成。

  2)安裝android-ndk開(kāi)發(fā)包,這個(gè)開(kāi)發(fā)包可以在google android 官網(wǎng)下載: 通過(guò)這個(gè)開(kāi)發(fā)包的工具才能將android jni 的C/C++的代碼編譯成庫(kù)

  3)android應(yīng)用程序開(kāi)發(fā)環(huán)境: 包括eclipse、java、 android sdk、 adt等。

  如何下載和安裝android-ndk我這里就不啰嗦了,安裝完之后,需要將android-ndk的路勁加到環(huán)境變量PATH中:

    sudo gedit /etc/environment

  在environment的PATH環(huán)境變量中添加你的android-ndk的安裝路勁,然后再讓這個(gè)更改的環(huán)境變量立即生效:

     source  /etc/environment

  經(jīng)過(guò)了上述步驟,在命令行下敲:

    ndk-bulid

  彈出如下的錯(cuò)誤,而不是說(shuō)ndk-build not found,就說(shuō)明ndk環(huán)境已經(jīng)安裝成功了。

    Android NDK: Could not find application project directory !   
    Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.   
    /home/braincol/workspace/android/android-ndk-r5/build/core/build-local.mk:85: *** Android NDK: Aborting    .  Stop.

 2.代碼的編寫(xiě)

  1)首先是寫(xiě)java代碼

  建立一個(gè)Android應(yīng)用工程HelloJni,創(chuàng)建HelloJni.java文件:

  HelloJni.java :

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;

public class HelloJni extends Activity
{
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    TextView tv = new TextView(this);
    tv.setText( stringFromJNI() );
    setContentView(tv);
  }


  /* A native method that is implemented by the 'hello-jni' native library, which is packaged with this application. */
  public native String stringFromJNI();

  public native String unimplementedStringFromJNI();



  /* this is used to load the 'hello-jni' library on application startup. The library has already been unpacked into

   /data/data/com.example.HelloJni/lib/libhello-jni.so at installation time by the package manager. */
  static {
    System.loadLibrary("hello-jni");
  }
}

  這段代碼很簡(jiǎn)單,注釋也很清晰,這里只提兩點(diǎn)::

static{
System.loadLibrary("hello-jni");
}

  表明程序開(kāi)始運(yùn)行的時(shí)候會(huì)加載hello-jni, static區(qū)聲明的代碼會(huì)先于onCreate方法執(zhí)行。如果你的程序中有多個(gè)類(lèi),而且如果HelloJni這個(gè)類(lèi)不是你應(yīng)用程序的入口,那么hello-jni(完整的名字是libhello-jni.so)這個(gè)庫(kù)會(huì)在第一次使用HelloJni這個(gè)類(lèi)的時(shí)候加載。

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

  可以看到這兩個(gè)方法的聲明中有 native 關(guān)鍵字, 這個(gè)關(guān)鍵字表示這兩個(gè)方法是本地方法,也就是說(shuō)這兩個(gè)方法是通過(guò)本地代碼(C/C++)實(shí)現(xiàn)的,在java代碼中僅僅是聲明。

  用eclipse編譯該工程,生成相應(yīng)的.class文件,這步必須在下一步之前完成,因?yàn)樯?h文件需要用到相應(yīng)的.class文件。

2)編寫(xiě)相應(yīng)的C/C++代碼

  剛開(kāi)始學(xué)的時(shí)候,有個(gè)問(wèn)題會(huì)讓人很困惑,相應(yīng)的C/C++代碼如何編寫(xiě),函數(shù)名如何定義? 這里講一個(gè)方法,利用javah這個(gè)工具生成相應(yīng)的.h文件,然后根據(jù)這個(gè).h文件編寫(xiě)相應(yīng)的C/C++代碼。

  a. 生成相應(yīng).h文件:

  就拿我這的環(huán)境來(lái)說(shuō),首先在終端下進(jìn)入剛剛建立的HelloJni工程的目錄:

braincol@ubuntu:~$ cd workspace/android/NDK/hello-jni/

  ls查看工程文件  

braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ls
AndroidManifest.xml  assets  bin  default.properties  gen  res  src

  可以看到目前僅僅有幾個(gè)標(biāo)準(zhǔn)的android應(yīng)用程序的文件(夾)。

  首先我們?cè)诠こ棠夸浵陆⒁粋€(gè)jni文件夾:

braincol@ubuntu:~/workspace/android/NDK/hello-jni$ mkdir jni
braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ls
AndroidManifest.xml  assets  bin  default.properties  gen  jni  res  src

  下面就可以生成相應(yīng)的.h文件了:

braincol@ubuntu:~/workspace/android/NDK/hello-jni$ javah -classpath bin -d jni com.example.hellojni.HelloJni
  -classpath bin:表示類(lèi)的路勁

  -d jni: 表示生成的頭文件存放的目錄

  com.example.hellojni.HelloJni 則是完整類(lèi)名

  這一步的成功要建立在已經(jīng)在 bin/com/example/hellojni/  目錄下生成了 HelloJni.class的基礎(chǔ)之上?,F(xiàn)在可以看到j(luò)ni目錄下多了個(gè).h文件:

braincol@ubuntu:~/workspace/android/NDK/hello-jni$ cd jni/
braincol@ubuntu:~/workspace/android/NDK/hello-jni/jni$ ls
com_example_hellojni_HelloJni.h

  我們來(lái)看看com_example_hellojni_HelloJni.h的內(nèi)容:

  com_example_hellojni_HelloJni.h :

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class com_example_hellojni_HelloJni */

#ifndef _Included_com_example_hellojni_HelloJni

#define _Included_com_example_hellojni_HelloJni

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:   com_example_hellojni_HelloJni

 * Method:  stringFromJNI

 * Signature: ()Ljava/lang/String;

 */

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI

 (JNIEnv *, jobject);


/*

 * Class:   com_example_hellojni_HelloJni

 * Method:  unimplementedStringFromJNI

 * Signature: ()Ljava/lang/String;

 */

JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_unimplementedStringFromJNI

 (JNIEnv *, jobject);


#ifdef __cplusplus

}

#endif

#endif

  上面代碼中的JNIEXPORT 和 JNICALL 是jni的宏,在android的jni中不需要,當(dāng)然寫(xiě)上去也不會(huì)有錯(cuò)。從上面的源碼中可以看出這個(gè)函數(shù)名那是相當(dāng)?shù)拈L(zhǎng)啊。。。。 不過(guò)還是很有規(guī)律的, 完全按照:java_pacakege_class_mathod 形式來(lái)命名。

  也就是說(shuō):

  Hello.java中 stringFromJNI() 方法對(duì)應(yīng)于 C/C++中的 Java_com_example_hellojni_HelloJni_stringFromJNI() 方法

  HelloJni.java中的 unimplementedStringFromJNI() 方法對(duì)應(yīng)于 C/C++中的 Java_com_example_hellojni_HelloJni_unimplementedStringFromJNI() 方法

  注意下其中的注釋?zhuān)?/p>

  Signature: ()Ljava/lang/String;

  ()Ljava/lang/String;()表示函數(shù)的參數(shù)為空(這里為空是指除了JNIEnv *, jobject 這兩個(gè)參數(shù)之外沒(méi)有其他參數(shù),JNIEnv*, jobject是所有jni函數(shù)必有的兩個(gè)參數(shù),分別表示jni環(huán)境和對(duì)應(yīng)的java類(lèi)(或?qū)ο螅┍旧恚?,Ljava/lang/String; 表示函數(shù)的返回值是java的String對(duì)象。

b. 編寫(xiě)相應(yīng)的.c文件:

  hello-jni.c :

#include <string.h>
#include <jni.h>


/* This is a trivial JNI example where we use a native method

 * to return a new VM String. See the corresponding Java source

 * file located at:

 *  apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java

 */

jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz )
{
  return (*env)->NewStringUTF(env, "Hello from JNI !");
}

  這里只是實(shí)現(xiàn)了Java_com_example_hellojni_HelloJni_stringFromJNI方法,而 Java_com_example_hellojni_HelloJni_unimplementedStringFromJNI 方法并沒(méi)有實(shí)現(xiàn),因?yàn)樵贖elloJni.java中只調(diào)用了stringFromJNI()方法,所以u(píng)nimplementedStringFromJNI()方法沒(méi)有實(shí)現(xiàn)也沒(méi)關(guān)系,不過(guò)建議最好還是把所有java中定義的本地方法都實(shí)現(xiàn)了,寫(xiě)個(gè)空函數(shù)也行啊。。。有總比沒(méi)有好。

  Java_com_example_hellojni_HelloJni_stringFromJNI() 函數(shù)只是簡(jiǎn)單的返回了一個(gè)內(nèi)容為 "Hello from JNI !" 的jstring對(duì)象(對(duì)應(yīng)于java中的String對(duì)象)。hello-jni.c文件已經(jīng)編寫(xiě)好了,現(xiàn)在可以把com_example_hellojni_HelloJni.h文件給刪了,當(dāng)然留著也行,只是我還是習(xí)慣把不需要的文件給清理干凈了。

3)編譯hello-jni.c 生成相應(yīng)的庫(kù)

a 編寫(xiě)Android.mk文件

  在jni目錄下(即hello-jni.c 同級(jí)目錄下)新建一個(gè)Android.mk文件,Android.mk 文件是Android 的 makefile文件,內(nèi)容如下:

# Copyright (C) 2009 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#   http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#

 
LOCAL_PATH := $(call my-dir)

 

include $(CLEAR_VARS)

 

LOCAL_MODULE  := hello-jni

LOCAL_SRC_FILES := hello-jni.c

 

include $(BUILD_SHARED_LIBRARY)

  這個(gè)Androd.mk文件很短,下面我們來(lái)逐行解釋下:

    LOCAL_PATH := $(call my-dir)

  一個(gè)Android.mk 文件首先必須定義好LOCAL_PATH變量。它用于在開(kāi)發(fā)樹(shù)中查找源文件。在這個(gè)例子中,宏函數(shù)'my-dir', 由編譯系統(tǒng)提供,用于返回當(dāng)前路徑(即包含Android.mk file文件的目錄)。

    include $( CLEAR_VARS)

  CLEAR_VARS由編譯系統(tǒng)提供,指定讓GNU MAKEFILE為你清除許多LOCAL_XXX變量(例如 LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...), 除LOCAL_PATH 。這是必要的,因?yàn)樗械木幾g控制文件都在同一個(gè)GNU MAKE執(zhí)行環(huán)境中,所有的變量都是全局的。

    LOCAL_MODULE := hello-jni

  編譯的目標(biāo)對(duì)象,LOCAL_MODULE變量必須定義,以標(biāo)識(shí)你在Android.mk文件中描述的每個(gè)模塊。名稱(chēng)必須是唯一的,而且不包含任何空格。

注意:編譯系統(tǒng)會(huì)自動(dòng)產(chǎn)生合適的前綴和后綴,換句話說(shuō),一個(gè)被命名為'hello-jni'的共享庫(kù)模塊,將會(huì)生成'libhello-jni.so'文件。

  重要注意事項(xiàng):如果你把庫(kù)命名為‘libhello-jni',編譯系統(tǒng)將不會(huì)添加任何的lib前綴,也會(huì)生成 'libhello-jni.so',這是為了支持來(lái)源于Android平臺(tái)的源代碼的Android.mk文件,如果你確實(shí)需要這么做的話。

    LOCAL_SRC_FILES := hello-jni.c

  LOCAL_SRC_FILES變量必須包含將要編譯打包進(jìn)模塊中的C或C++源代碼文件。注意,你不用在這里列出頭文件和包含文件,因?yàn)榫幾g系統(tǒng)將會(huì)自動(dòng)為你找出依賴型的文件;僅僅列出直接傳遞給編譯器的源代碼文件就好。

  注意,默認(rèn)的C++源碼文件的擴(kuò)展名是'.cpp'. 指定一個(gè)不同的擴(kuò)展名也是可能的,只要定義LOCAL_DEFAULT_CPP_EXTENSION變量,不要忘記開(kāi)始的小圓點(diǎn)(也就是'.cxx',而不是'cxx')

    include $(BUILD_SHARED_LIBRARY)

  BUILD_SHARED_LIBRARY表示編譯生成共享庫(kù),是編譯系統(tǒng)提供的變量,指向一個(gè)GNU Makefile腳本,負(fù)責(zé)收集自從上次調(diào)用'include $(CLEAR_VARS)'以來(lái),定義在LOCAL_XXX變量中的所有信息,并且決定編譯什么,如何正確地去做。還有 BUILD_STATIC_LIBRARY變量表示生成靜態(tài)庫(kù):lib$(LOCAL_MODULE).a, BUILD_EXECUTABLE 表示生成可執(zhí)行文件。

b. 生成.so共享庫(kù)文件

  Andro文件已經(jīng)編寫(xiě)好了,現(xiàn)在可以用android NDK開(kāi)發(fā)包中的 ndk-build腳本生成對(duì)應(yīng)的.so共享庫(kù)了,方法如下:

    braincol@ubuntu:~/workspace/android/NDK/hello-jni/jni$ cd ..
    braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ls
    AndroidManifest.xml  assets  bin  default.properties  gen  jni  libs  obj  res  src
    braincol@ubuntu:~/workspace/android/NDK/hello-jni$ ndk-build
    Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
    Gdbsetup       : libs/armeabi/gdb.setup
    Install        : libhello-jni.so => libs/armeabi/libhello-jni.so

  可以看到已經(jīng)正確的生成了libhello-jni.so共享庫(kù)了, 我們?nèi)?libs/armeabi/ 目錄下看看:

    braincol@ubuntu:~/workspace/android/NDK/hello-jni$ cd libs/
    braincol@ubuntu:~/workspace/android/NDK/hello-jni/libs$ ls
    armeabi
    braincol@ubuntu:~/workspace/android/NDK/hello-jni/libs$ cd armeabi/
    braincol@ubuntu:~/workspace/android/NDK/hello-jni/libs/armeabi$ ls
    gdbserver  gdb.setup  libhello-jni.so

4)在eclipse重新編譯HelloJni工程,生成apk

  eclipse中刷新下HelloJni工程,重新編譯生成apk,libhello-jni.so共享庫(kù)會(huì)一起打包在apk文件內(nèi)。在模擬器中看看運(yùn)行結(jié)果。

 以上就是Android NDK開(kāi)發(fā)的資料整理,后續(xù)繼續(xù)補(bǔ)充相關(guān)資料,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • Android實(shí)現(xiàn)設(shè)置APP灰白模式效果

    Android實(shí)現(xiàn)設(shè)置APP灰白模式效果

    大家好,本篇文章主要講的是Android實(shí)現(xiàn)設(shè)置APP灰白模式效果,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Android自定義View實(shí)現(xiàn)閃耀字體效果

    Android自定義View實(shí)現(xiàn)閃耀字體效果

    這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)閃耀字體效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android?Activity共享元素動(dòng)畫(huà)示例解析

    Android?Activity共享元素動(dòng)畫(huà)示例解析

    這篇文章主要為大家介紹了Android?Activity共享元素動(dòng)畫(huà)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Android超詳細(xì)講解組件AdapterView的使用

    Android超詳細(xì)講解組件AdapterView的使用

    AdapterView組件是一組重要的組件,AdapterView本身是一個(gè)抽象基類(lèi),它派生的子類(lèi)在用法上十分相似,從AdapterView派生出的三個(gè)子類(lèi):AdsListView、AdsSpinner、AdapterViewAnimator,這3個(gè)子類(lèi)依然是抽象的,實(shí)際運(yùn)用時(shí)需要它們的子類(lèi)
    2022-03-03
  • 詳解Android官方架構(gòu)中UseCase

    詳解Android官方架構(gòu)中UseCase

    這篇文章主要為大家介紹了Android?官方架構(gòu)中的?UseCase?該怎么寫(xiě)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Android實(shí)現(xiàn)自定義dialog的代碼

    Android實(shí)現(xiàn)自定義dialog的代碼

    這篇文章主要介紹了Android實(shí)現(xiàn)自定義dialog的實(shí)例代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • Android自定義表格控件滿足人們對(duì)視覺(jué)的需求

    Android自定義表格控件滿足人們對(duì)視覺(jué)的需求

    隨著人們對(duì)視覺(jué)的需求,基本組件已無(wú)法滿足人們求新求異的要求,于是我們常常會(huì)自定義組件,用來(lái)實(shí)現(xiàn)更美觀的UI界面,接下來(lái)將介紹Android如何自定義表格控件,感興趣的朋友可以了解下,或許對(duì)你學(xué)習(xí)自定義控件有所幫助
    2013-02-02
  • Android編程中Tween動(dòng)畫(huà)和Frame動(dòng)畫(huà)實(shí)例分析

    Android編程中Tween動(dòng)畫(huà)和Frame動(dòng)畫(huà)實(shí)例分析

    這篇文章主要介紹了Android編程中Tween動(dòng)畫(huà)和Frame動(dòng)畫(huà),結(jié)合實(shí)例形式較為詳細(xì)的分析了Android中Tween動(dòng)畫(huà)和Frame動(dòng)畫(huà)的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-12-12
  • android按行讀取文件內(nèi)容的幾個(gè)方法

    android按行讀取文件內(nèi)容的幾個(gè)方法

    這篇文章主要介紹了android按行讀取文件內(nèi)容的幾個(gè)方法,java逐行讀取文件內(nèi)容的幾個(gè)方法,需要的朋友可以參考下
    2014-06-06
  • Android創(chuàng)建外部lib庫(kù)及自定義View的圖文教程

    Android創(chuàng)建外部lib庫(kù)及自定義View的圖文教程

    這篇文章主要給大家介紹了關(guān)于Android創(chuàng)建外部lib庫(kù)及自定義View的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11

最新評(píng)論