事前準備
本指南假設您已掌握原生程式設計和 Android 開發中的概念。
簡介
本節會概略解釋 NDK 的運作方式。Android NDK 是我們推出的一套工具,讓您可以將 C 或 C++ (「原生程式碼」) 嵌入 Android 應用程式中。如果是想要執行以下一或多項操作的開發人員,則在 Android 應用程式中使用原生程式碼的功能特別實用:
- 在不同平台之間移植應用程式。
- 重複使用現有的程式庫,或開放自己的程式庫供他人重複使用。
- 提高特定情況下的效能,特別是需要大量運算的情況下 例如遊戲
運作方式
本節介紹建立 Android 原生應用程式時使用的主要元件,然後說明建立和封裝程序。
主要元件
在建立應用程式時,您應該瞭解一下以下元件:
原生共享程式庫:NDK 會從 C/C++ 原始碼建構這些程式庫或
.so
檔案。原生靜態程式庫:NDK 也可以建構靜態程式庫或
.a
檔案,而您可以將這些檔案連結至其他程式庫。Java Native Interface (JNI):JNI 是 Java 與 C++ 元件通訊時所用的介面。本指南介紹 JNI 的相關知識;如要瞭解與 JNI 相關的資訊,請參閱 Java Native Interface 規範。
應用程式二進位檔介面 (ABI):ABI 明確定義應用程式機器碼與執行階段系統互動的方式。NDK 會根據這些定義建立
.so
檔案。不同的 ABI 會對應到不同的架構:NDK 支援 32 位元 ARM、AArch64、x86 和 x86-64 的 ABI。詳情請參閱 Android ABI。資訊清單:如要編寫不含 Java 元件的應用程式,必須在資訊清單中宣告 NativeActivity 類別。請參閱使用 native_activity.h 介面的內容,進一步瞭解如何宣告。
流程
開發 Android 原生應用程式的一般流程如下:
設計應用程式、決定要在 Java 中實作的部分,以及要以原生程式碼的形式實作的部分。
您可以比照建立其他 Android 專案的方式,建立一個 Android 應用程式專案。
如要編寫僅限原生的應用程式,請在
AndroidManifest.xml
中宣告 NativeActivity 類別。詳情請參閱原生活動和應用程式。建立提供原生資料庫說明的
Android.mk
檔案,包括名稱、旗標、已連結的程式庫和要在「JNI」目錄中編譯的來源檔案。您也可以視需要建立
Application.mk
檔案來設定目標 ABI、工具鏈、發布/偵錯模式和 STL。如果並未針對上述任何一項指定值,則系統將分別套用下列預設值:- ABI:所有未淘汰的 ABI
- 模式:發布
- STL:系統
將原生來源存放在專案的
jni
目錄下。使用 ndk-build 編譯原生 (
.so
、.a
) 程式庫。建立 Java 元件,產生可執行的
.dex
檔案。將
.so
、.dex
以及執行應用程式所需的其他檔案等所有內容封裝至 APK 檔案。
原生活動和應用程式
Android SDK 提供 NativeActivity 輔助類別,讓您可以編寫完全原生的活動。NativeActivity 會處理 Android 架構與原生程式碼之間的通訊,因此您無需為其建立子類別或呼叫方法,只需在 AndroidManifest.xml
檔案中將應用程式宣告為原生,然後開始建立原生應用程式即可。
使用 NativeActivity 的 Android 應用程式仍會在其虛擬機器中執行,並以沙箱的形式與其他應用程式分隔。因此,您仍可透過 JNI 存取 Android 架構 API。在某些情況下 (例如用於感應器、輸入事件和資產),NDK 提供可用的原生介面,讓您無需透過 JNI 呼叫。如要進一步瞭解此類支援,請參閱原生 API。
無論您是否在開發原生活動,我們建議您使用傳統 Android 建立工具建立專案,這有助於確保以正確的結構建立及封裝 Android 應用程式。
Android NDK 提供以下 2 種實作原生活動的方式:
- native_activity.h 標頭會定義原生版本的 NativeActivity 類別,當中包含建立原生活動所需的回呼介面和資料結構。由於應用程式的主執行緒會處理回呼,因此不得封鎖您的回呼實作。否則,您可能會因為主執行緒在回呼傳回前沒有回應,而收到 ANR (應用程式無回應) 錯誤。
android_native_app_glue.h
檔案會定義在 native_activity.h 介面頂端建構的靜態輔助程式庫。這會產生另一個執行緒,用於處理事件迴圈中的回呼或輸入事件等。將這些事件移至另一個執行緒,可防止任何回呼封鎖主執行緒。
您也可以使用 <ndk_root>/sources/android/native_app_glue/android_native_app_glue.c
來源來修改實作。
如要進一步瞭解如何使用此靜態程式庫,請參閱原生活動範例應用程式及其說明文件。此外,您亦可查看 <ndk_root>/sources/android/native_app_glue/android_native_app_glue.h
檔案中的註解,以便瞭解更多資訊。
使用 native_activity.h 介面
如要透過 native_activity.h 介面實作原生活動,請執行以下操作:
在專案的根目錄中建立
jni/
目錄,這個目錄會儲存所有原生程式碼。在
AndroidManifest.xml
檔案中宣告您的原生活動。由於您的應用程式沒有 Java 程式碼,因此請將
android:hasCode
設為false
。<application android:label="@string/app_name" android:hasCode="false">
您必須將活動標記的
android:name
屬性設為 NativeActivity。<activity android:name="android.app.NativeActivity" android:label="@string/app_name">
meta-data
標記的android:value
屬性會指定含有應用程式進入點的共享程式庫名稱 (例如 C/C++main
),同時會省略程式庫名稱中的lib
前置字串和.so
後置字串。<manifest> <application> <activity> <meta-data android:name="android.app.lib_name" android:value="native-activity" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
建立用於原生活動的檔案,並實作 ANativeActivity_onCreate 變數中指定的函式。應用程式會在原生活動啟動時呼叫此函式。此函式與 C/C++ 中的
main
相似,它會接收 ANativeActivity 結構的指標,而此結構中包含需要編寫的各個回呼實作的函式指標。在ANativeActivity->callbacks
中,將適用的回呼函式指標設為回呼的實作。將
ANativeActivity->instance
欄位設為您要使用的任何特定資料的執行個體位址。實作您希望活動在啟動時執行的其他操作。
實作您在
ANativeActivity->callbacks
中設定的其他回呼。如要進一步瞭解系統呼叫回呼的時機,請參閱管理活動生命週期。開發應用程式的其他部分。
在專案的
jni/
目錄中建立Android.mk file
以向建構系統描述原生模組。詳情請參閱 Android.mk。取得 Android.mk 檔案後,請透過
ndk-build
指令編譯您的原生程式碼。cd <path>/<to>/<project> $NDK/ndk-build
依照平常的方式建立及安裝 Android 專案。如果原生程式碼位於
jni/
目錄中,則建立指令碼會自動將根據原生程式碼建立的.so
檔案封裝至 APK。
其他程式碼範例
如要下載 NDK 範例,請參閱 NDK 範例。