Android NDK開發,JNI通識與NDK配置

軟件 編程語言 腳本語言 Google文檔 天下訪談 2017-03-27

NI通識

NDK是什麼

原生開發工具包 (NDK) 是一組可讓您在 Android 應用中利用 C 和 C++ 代碼的工具。 可用以從您自己的源代碼構建,或者利用現有的預構建庫。

-來自Google 官方文檔

為什麼要使用NDK

  • 從設備獲取卓越性能以用於計算密集型應用,例如遊戲或物理模擬。

  • 重複使用您自己或其他開發者的 C 或 C++ 庫。

如果不滿足上面的條件, 那麼你還是不要引入NDK, 這樣會把你的應用變得非常非常地複雜.

主要組件

ndk-build

ndk-build 腳本用於在 NDK 中心啟動構建腳本

Java

Android 構建過程從 Java 來源生成 .dex (Dalvik EXecutable) 文件,這些文件是 Android OS 在 Dalvik 虛擬機(“DVM”)中運行的文件。 即使您的應用根本未包含任何 Java 源代碼,構建過程仍會生成原生組件在其中運行的 .dex 可執行文件。

原生共享庫

NDK 從原生源代碼構建這些庫或 .so 文件。

原生靜態庫

NDK 也可構建靜態庫或 .a 文件,您可以關聯到其他庫。

Java 原生接口 (JNI)

JNI 是 Java 和 C++ 組件用以互相溝通的接口。

應用二進制界面 (ABI)

ABI 可以非常精確地定義應用的機器代碼在運行時如何與系統交互。 NDK 根據這些定義構建 .so 文件。 不同的 ABI 對應不同的架構:NDK 包含對 ARMEABI(默認)、MIPS 和 x86 的 ABI 支持。

清單文件

如果您要編寫沒有 Java 組件的應用,必須在清單文件中聲明 NativeActivity 類。

兩個重要的配置文件

Android.mk

必須在 jni 文件夾內創建 Android.mk 配置文件。 ndk-build 腳本將查看此文件,其中定義了模塊及其名稱、要編譯的源文件、版本標誌以及要鏈接的庫。

概覽

Android.mk 文件位於項目 jni/ 目錄的子目錄中,用於向構建系統描述源文件和共享庫。事實上就是告訴ndk去編譯哪些c/c++文件還有怎麼去編譯它們

NDK定義的變量

常用

編譯目標目錄聲明

LOCAL_PATH := $(call my-dir)

必須定義, LOCAL_PATH表示需要編譯的源文件的目錄, $(call my-dir)表示使用宏函數my-dir的返回值, 對應的就是當前Android.mk的所在目錄

重置全局變量

include $(CLEAR_VARS)

CLEAR_VARS變量指向特殊 GNU Makefile, 可為您清除許多LOCAL_XXX變量. 不包括LOCAL_PATH 因為系統在單一 GNU Make 執行環境(其中所有變量都是全局的)中解析所有構建控制文件. 在描述每個模塊之前, 必須聲明(重新聲明)此變量

指定需要編譯的模塊

LOCAL_MODULE := recorder-jni

LOCAL_MODULE指定模塊的名稱, 唯一且不含空格, 之後會編譯出librecorder-jni.so, 如果模塊名已包含前綴lib, 則不會自動添加lib前綴.

LOCAL_SRC_FILES表示該模塊需要編譯哪些源文件, 多個源文件使用空格分割

上面的意思就是, 編譯video.c和audio.c並輸出為librecorder-jni.so

整合

include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY變量指向GNU Makefile腳本, 用於收集您自最近 include 後在 LOCAL_XXX 變量中定義的所有信息. 其實就是讓上一次include到這裡之間的內容生效

如果引用了其他的so文件, 那麼ndk會清掉庫目錄下的所有so文件, 默認是jnilibs, 所以必須使用預構建庫解決這問題

其他

構建系統提供許多可用於 Android.mk 文件中的變量。其中許多變量已預先賦值。 另一些變量由您賦值。

除了這些變量之外,您還可以定義自己的任意變量。在定義變量時請注意,NDK 構建系統會預留以下變量名稱:

  • 以 LOCAL_ 開頭的名稱,例如 LOCAL_MODULE。

  • 以 PRIVATE_、NDK_ 或 APP 開頭的名稱。構建系統在內部使用這些變量。

  • 小寫名稱,例如 my-dir。構建系統也是在內部使用這些變量。

    如果為了方便而需要在 Android.mk 文件中定義自己的變量,建議在名稱前附加 MY_。

編譯指定平臺庫

TARGET_ARCH_ABI := arm64-v8a

當構建系統解析此 Android.mk 文件時,此變量將 CPU 和架構的名稱存儲到目標。 您可以指定以下一個或多個值,使用空格作為多個目標之間的分隔符。其實就是指定需要編譯的平臺

CPU和架構設置
ARMv5TEarmeabi
ARMv7armeabi-v7a
ARMv8 AArch64arm64-v8a
i686x86
x86-64x86_64
mips32 (r1)mips
mips64 (r6)mips64
全部all

指定Android版本

TARGET_PLATFORM := android-22

作為構建系統目標的 Android API 級別號

更多請參考Google文檔的NDK 定義的變量

模塊描述的變量

每個模塊描述應遵守以下基本流程:

  • 使用 CLEAR_VARS 變量初始化或取消定義與模塊相關的變量。

  • 為用於描述模塊的變量賦值。

  • 使用 BUILD_XXX 變量設置 NDK 構建系統,以便為模塊使用適當的構建腳本。

編譯目錄路徑

LOCAL_PATH, 表示需要編譯的源文件的目錄

編譯模塊名稱

LOCAL_MODULE, 指定模塊的名稱, 唯一且不含空格, 之後會編譯出librecorder-jni.so, 如果模塊名已包含前綴lib, 則不會自動添加lib前綴.

編譯模塊輸出名稱

LOCAL_MODULE_FILENAME, 真正的庫輸出文件名. 如果不喜歡系統自動生成的文件名, 可以指定這個值

LOCAL_MODULE := foo

上面表示輸出libnewfoo.so

更多參考Google文檔的模塊描述變量

待編譯的源文件

LOCAL_SRC_FILES,指定源文件列表, 多個文件使用空格分割. 可以使用相對文件路徑(指向 LOCAL_PATH)和絕對文件路徑

Application.mk

此文件枚舉並描述您的應用需要的模塊。 Android.mk有效的前提是依靠該文件的保證 位於jni的目錄下

該文件信息包括:

  • 用於針對特定平臺進行編譯的 ABI。

  • 工具鏈。

  • 要包含的標準庫(靜態和動態 STLport 或默認系統)。

工程路徑

APP_PROJECT_PATH, 應用項目根目錄的絕對路徑. 如果將Application.mk 文件放在 $NDK/apps/<myapp>/ 下,則必須定義此變量。 如果將其放在 $PROJECT/jni/ 下,則此變量可選。

編譯平臺

APP_ABI, 默認情況下, NDK 構建系統為 armeabi ABI 生成機器代碼.多個值使用空格分割

指令集
基於 ARMv7 的設備上的硬件 FPU 指令APP_ABI := armeabi-v7a
ARMv8 AArch64APP_ABI := arm64-v8a
IA-32APP_ABI := x86
Intel64APP_ABI := x86_64
MIPS32APP_ABI := mips
MIPS64 (r6)APP_ABI := mips64
所有支持的指令集APP_ABI := all

編譯Android版本

APP_PLATFORM, 此變量包含目標 Android 平臺的名稱.

其他

更多參考Google文檔的Application.mk

由於Android Studio以強大的方式集成了NDK, 所以上面很多配置都不需要寫. 方便了很多.

NDK配置

環境

環境版本
OSOSX 10.12.3
IDEAndroid Studio 2.3
JDKOracle JDK1.7

Android Studio 2.3集成NDK比以前方便多了, 因為NDK已經在SDK Manager中提供下載.

下載安裝

File->Settings->Appearance & Behavior->System Settings->Android SDK->SDK Tools->勾上NDK->Apply->OK

Android NDK開發,JNI通識與NDK配置

NDK配置.png

然後就開始下載了, 下載完成後finish就可以了.

相關推薦

推薦中...