NDK學習一指南(一)

image-20181224133832199

JNI和NDK是什麼?

基本概念

  • Android NDKhtml

    NDK是一組容許你將 C 或 C++嵌入到 Android 應用中的工具。經過NDK開發咱們能夠在平臺之間移植應用(音視頻開源庫FFmpeg、開源視覺庫OpenCV等等),在一些計算密集型的APP(好比遊戲開發)中咱們也須要作一些算法的移植工做。能夠看出來NDK就是原生開發工具包,在AndroidStudio中咱們在經過SDK Manager進行NDK工具包的更新和安裝。NDK是屬於Android的和Java沒有特定的關係。android

  • Android JNI算法

    Java Native InterfaceJava本地接口,JNI是屬於Java特有的特性,主要做用是讓Java和C++、C等其餘本地語言進行交互。經過JNI,可讓Java具有跨平臺的特性,加強Java和本地語言交互的能力。函數

NDK和JNI的關係

NDK是Android SDK自帶的工具開發包,用於快速的開發C和C++的動態代碼庫,並將相關的so文件打包進APK文件中。JNI是Java語言加強的特性之一,用於Java與本地語言的交互。總結下來:JNI是實現的終極目標,而NDK是Android集成開發環境實現JNI目標的手段。經過NDK實現JNI目標。工具

須要注意: NDK提供的庫自己也是有限的,僅僅用於處理算法效率和敏感的問題,NDK提供了交叉編譯器,用於生成特定的CPU的平臺動態庫,另外NDK還提供了.so文件和.apk打包的工具。開發工具

AndroidStudio如何支持開發

還記的AndroidStudio2.2的版本嗎?還記得Eclipse開發NDK嗎?簡直苦不堪言啊。考慮到目前大部分同窗已經遷移到AndroidStudio,何況我相信絕大同窗的版本已經在3.2了吧。咱們直接就講解最新的AndroidStudio集成NDK開發的方式。gradle

  • 保證你的Android SDK已經下載了Cmake、LLDB、NDK。

image-20181224142135487

  • 經過AndroidStudio建立Android Project,記得勾選Include C++ surpport

image-20181224142447705

  • 點擊Next,一直到Customize C++ Support,勾選-fexceptions和-frtti

image-20181224142937266

一個支持了NDK的Android的項目有哪些須要注意的點呢?ui

  • Gradle配置

若是要手動將 Gradle 與你的本地庫相關聯,你須要在 module 層級的 build.gradle 文件中添加 externalNativeBuild {} 代碼塊,而且在該代碼塊中配置 cmake {}ndkBuild {}。能夠看到AndroidStudio默認使用Cmake構建系統。後續咱們着重來講。spa

image-20181224143508987

cmake {
    cppFlags "-frtti -fexceptions" //這裏的設置了一些可選的標識符給C++的編譯器,這也是咱們以前在建立項目時候勾選的
}
複製代碼
  • Cmake配置

image-20181224144056905

add_library()find_librarytarget_link_libraries都是Cmake腳本中定義的命令函數。其餘一些Cmake腳本語法能夠參見https://cmake.org/cmake/help/v3.0/command/find_library.html(注意版本區分)。插件

add_library 使用指定的源文件向工程中添加一個庫。函數原型以下:

add_library(<name> [STATIC | SHARED | MODULE]
              [EXCLUDE_FROM_ALL]
              source1 source2 ... sourceN)
             # STATIC:靜態庫,是目標文件的歸檔文件,在連接其它目標的時候使用
             # SHARED:動態庫,會被動態連接,在運行時被加載
             # MODULE:模塊庫,是不會被連接到其它目標中的插件,可是可能會在運行時使用dlopen-系列的函數
複製代碼

find_library用於查找一個庫文件。函數原型以下:

find_library(
             <VAR>
             name | NAMES name1 [name2 ...]
             [HINTS path1 [path2 ... ENV var]]
             [PATHS path1 [path2 ... ENV var]]
             [PATH_SUFFIXES suffix1 [suffix2 ...]]
             [DOC "cache documentation string"]
             [NO_DEFAULT_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_CMAKE_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_SYSTEM_PATH]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH]
            )
           # android系統每一個類型的庫會存放一個特定的位置,而log庫存放在log-lib中
複製代碼

target_link_libraries設置要連接的庫文件的名稱。函數原型以下:

target_link_libraries(<target> [item1 [item2 [...]]]
                      [[debug|optimized|general] <item>] ...)
複製代碼

經過上面的解析,咱們知道AndroidStudio默認使用Cmake進行NDK構建環境,經過在CMakeLists.txt中進行編輯命令的編寫,使得C++/C的代碼能夠經過Cmake工具進行編譯。

  • Java和C++代碼JNI編寫

Java:函數的native申明是在MainActivity中。咱們再看看MainActivity文件,與之前的jni調用方式完成同樣,包括了庫的加載、native方法申明、jni方法調用三個過程。在native方法中經過點擊鼠標左鍵能夠直接跳轉到C++的源碼裏。

image-20181224145836640

C++:這裏是咱們須要經過C/C++進行代碼編寫的地方。

image-20181224150322849

咱們在AndroidStudio中進行運行,把項目跑到手機中,當咱們點擊TextView,咱們能夠看到Hello from C++,說明咱們成功進行了Java和C++代碼的相互調用,也完成了JNI第一個入門程序的分析。

已有項目如何支持NDK開發

上面咱們看到了如何在項目剛剛建立的時候集成NDK開發,若是針對一個已經開發的項目,那麼如何進行NDK的集成呢?

  • 在須要使用JNI的模塊中新增一個CmakeLists.txt文件,按照Cmake語法規則進行腳本的編寫

image-20181224151310204

  • 配置項目支持JNI開發,在項目模塊右鍵選擇Link C++ Project with Gradle。

    image-20181224151702372

  • 在彈出的提示框中選擇剛新建配置的CMakeLists.txt文件,並點擊OK。

    image-20181224151924209

    經過上述的步驟,咱們能夠看到AndroidStudio會幫咱們在gradel腳本文件中自動建立externalNativeBuild {} 代碼塊,而且在該代碼塊中配置 cmake {} 代碼塊了。接下來咱們就能夠在Java代碼中進行庫的加載、native方法申明、jni方法調用三部曲了。

    如今,你是否是對NDK有了初步的瞭解了呢?後續將會進一步分享NDK,請你們保持關注。

相關文章
相關標籤/搜索