Learning Android 第十五章 NDK 翻譯一

來源:互聯網
上載者:User
 

第十五章 本地開發工具集(NDK)

 NDK,是協助你整合本地代碼的外加附件,所謂本地代碼就是在Android應用中使用一些平台特性,而這些平台特性通常是通過C或C++暴漏的API。NDK允許你的Android應用調用一些本地代碼乃至包含一些本地庫。在Android的薑餅(Gingerbread)版,NDK對本地代碼的支援更是提供了NativeActivity類。現在你可以用C或C++來寫整個activity了。然而,NativeActivity並不是本章的主題。在這裡,我們來看看如何在你的Java Android應用中整合本地C代碼。

 什麼是和什麼不是NDK要做的?

你在應用開發部分使用本地代碼的主要動機是效能。就像你看到的那樣,NDK很好的支援數學和映像庫,也很好的支援一些系統庫。所以,對於那些圖形和計算要求很強的應用,NDK是最好的候選。近來逐漸繁榮的流行手機遊戲以此來驅動就是一個不錯的證明。需要注意的是,任何通過Java本地介面(JNI)訪問你應用的本地代碼仍然在應用程式的Dalvik虛擬機器上運行。所以它服從與Android應用程式同樣的安全沙箱規則。用C或C++來編寫一部分也許Java並不適合的代碼並不是一個很好的使用NDK的理由。要記住很多低級的硬體特性已經很優美的通過Android架構暴露出來給Java,你可以隨意的使用它們。

 NDK解決的問題

NDK解決了一些你在做本地開發不得不處理的重要問題。

工具鏈

Java通過JNI提供了訪問本地代碼的入口。為使其工作,你可能不得不在你的主機上為目標架構編譯所有的東西,而這樣需要你在你的開發機器上擁有完整的工具鏈。安裝指定的跨平台編譯器和其他工具可不是簡單的事。NDK提供了完全的工具鏈,這樣你就可以編譯和構建本地代碼使其運行在你的目標平台上了。這個構建系統做成了很容易安裝你的環境並在項目中整合你的本地代碼。

 打包你的庫

如果你有一個本地庫並且你想要它在你的應用程式中可用,你一定要確定你的庫的路徑是系統載入庫的路徑。在Linux中,典型的路徑是LD_LIBRARY_PATH。在Android裝置上,只有/system/lib是系統載入的路徑。這裡有一個問題是因為整個/system區是唯讀,不能用來安裝庫。

NDK通過輸送你的本地庫使其成為應用程式套件組合(apk)的一部分的機制解決了這個問題。基本上,當使用者安裝一個包含本地庫的APK時,系統就建立一個名為/data/data/你的包/lib/的路徑。如果你回顧95頁的“檔案系統闡述”,這個路徑(partition)是此應用程式私人的,這是個安全的地方存放你的庫,它可以阻止其他應用程式載入和使用你的庫。這個打包機製為發布應用程式給Android裝置帶來了激動人心的變化,同時它也是一件大事,因為此機制給遊戲提供了巨大的複用範圍和新的本地代碼。

 文檔和標準標頭檔

NDK帶來了協助文檔和樣本程式來解釋如何使本地代碼工作。同時也標準化了一些C和C++的標頭檔,如:

• libc (C 庫) 標頭檔

• libm (數學庫) 標頭檔

• JNI介面標頭檔

• libz (Zlib壓縮) 標頭檔

• liblog (Android日誌) 標頭檔

• OpenGL ES 1.1和OpenGL ES2.0(3D圖形庫)標頭檔

• libjnigraphics (像素緩衝存取) 標頭檔(Android2.2及以上)

• 支援C++的mini標頭檔集

• OpenSL ES 本地音頻庫

• Android 本地應用API

 有了標準的標頭檔集,你可能會猜測(extrapolated)NDK對哪些更合適。在下一章節我們就會檢驗它。

 一個NDK的例子:斐波那契(Fibonacci)

因為NDK特別適合高強度的計算類應用,我想尋找一個這樣的例子,我們要能在本地代碼和Java代碼中實現一個相對簡單的演算法,並比較它們的相對速度。所以,我選擇了斐波那契演算法來做這個例子。這是一個簡單的演算法,可以很容易的在C和Java中實現。另外,我們還可以用遞迴(recursively)和迭代(iteratively)兩種方式。

先快速回顧一下,斐波那契數列的定義如下:

fib(0)=0

fib(1)=1

fib(n)=fib(n-1)+fib(n-2)

 斐波那契數列的排序類似於:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,等等

在這個例子中,我們將要:

•          建立一個java類來顯示斐波那契庫

•          建立本地代碼標頭檔

•          用C來實現本地代碼

•          編譯並構建一個共用庫

•          在Android activity中使用此本地代碼

 

 FibLib

FibLib是我們聲明計算斐波那契數列演算法的地方。我們總共有四個斐波那契演算法的版本:

•          Java 遞迴版本

•          Java 迭代版本

•          本地遞迴版本

•          本地迭代版本

 我們在Example 15-1中先寫一個Java的實現,然後用C再寫一個本地版本。

Example 15-1. FibLib.java

 

package com.marakana;public class FibLib {// Java implementation - recursivepublic static long fibJ(long n) { //注釋一if (n <= 0)return 0;if (n == 1)return 1;return fibJ(n - 1) + fibJ(n - 2);}// Java implementation - iterativepublic static long fibJI(long n) { //注釋二long previous = -1;long result = 1;for (long i = 0; i <= n; i++) {long sum = result + previous;previous = result;result = sum;}return result;}// Native implementationstatic {System.loadLibrary("fib"); //注釋三}// Native implementation - recursivepublic static native long fibN(int n); //注釋四// Native implementation - iterativepublic static native long fibNI(int n); //注釋五}

注釋一:這是斐波那契遞迴演算法的Java遞迴版本

注釋二:這是相同Java遞迴演算法的迭代版本。實現遞迴演算法的任務都可以分解為迭代演算法。

注釋三:本地版本要實現一個共用庫。這裡,我們告訴Java虛擬機器來載入這個庫,當調用時這個函數就會被尋找到。

注釋四:我們聲明本地斐波那契方法,但並沒有實現它。注意要在這裡使用native關鍵字。它告訴Java虛擬機器實現的這個方法在這個共用庫中。這個庫要在函數調用之前(prior to)載入。

注釋五:前一個聲明是為本地遞迴版本的,這個是為迭代版本的。

 

到這裡,我們的Fiblib就完成了。但是我們還是需要回到用C來實現本地方法,首先,我們需要建立一個適當的(appropriate)JNI標頭檔。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.