原生開發套件 (NDK) 是一套工具,使您能夠在 Android 應用中使用 C 和 C++ 代碼。
使用 NDK 將 C 和 C++ 代碼編譯到原生庫中,然後使用 Android Studio 的集成構建系統 Gradle 將原生庫打包到 APK 中。Java 代碼隨後可以通過Java原生接口(JNI)調用原生庫中的函數。
NDK的作用:
- 進一步提升設備性能,以降低延遲,或運行計算密集型應用,如遊戲或物理模擬。
- 重複使用您自己或其他開發者的 C 或 C++ 庫。
Android Studio 編譯原生庫的默認構建工具是CMake。
1.下載NDK和工具:
應用編譯和調試原生代碼,您需要以下組件:
- Android 原生開發套件 (NDK):這套工具使您能在 Android 應用中使用 C 和 C++ 代碼。
- CMake:一款外部編譯工具,可與 Gradle 搭配使用來編譯原生庫。如果您只計劃使用 ndk-build,則不需要此組件。
- LLDB:Android Studio 用於調試原生代碼的調試程序。
2.創建CMake構建腳本:
CMake 構建腳本是一個純文本文件,必須將其命名爲 CMakeLists.txt
,並在其中包含 CMake 構建您的 C/C++ 庫時需要使用的命令。
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
# Specifies a path to native header files.
include_directories(src/main/cpp/include/)
find_library( # Defines the name of the path variable that stores the
# location of the NDK library.
log-lib
# Specifies the name of the NDK library that
# CMake needs to locate.
log )
# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the log library to the target library.
${log-lib} )
CMake命令解釋:
- cmake_minimum_required():設置CMake所需要的最小版本;
- add_library():設置共享庫的名字,設置共享類型,添加C/C++原生代碼;名字規範爲liblibrary-name.so,library-name爲庫名字,如libnative-lib.so共享庫爲native-lib,在Android中加載如下:
static {
System.loadLibrary("native-lib");
}
共享類型有:STATIC/SHARED/MUDULE,STATIC:是對象文件的存檔,用於鏈接其他目標;SHARED:靜態加載和運行時加載;MUDULE:是沒有鏈接到其他目標的插件,但是可以在運行時使用dlopen-link功能動態加載;
添加C/C++原生代碼:添加C/C++的相對路徑。
- find_library():以找到 NDK 庫並將其路徑存儲爲一個變量。可以使用此變量在構建腳本的其他部分引用 NDK 庫;
- target_link_libraries():爲了讓原生庫能夠調用如
log
庫中的函數;
關聯到原生庫:
- NDK 還以源代碼的形式包含一些庫,您將需要構建這些代碼並將其關聯到您的原生庫。您可以使用 CMake 構建腳本中的
add_library()
命令將源代碼編譯到原生庫中。要提供本地 NDK 庫的路徑,您可以使用 Android Studio 自動爲您定義的ANDROID_NDK
路徑變量,以下命令告訴 CMake 要編譯android_native_app_glue.c
(負責管理 NativeActivity生命週期事件和觸摸輸入),並將其鏈接到靜態庫native-lib
中:
add_library( app-glue
STATIC
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )
# You need to link static libraries against your shared native library.
target_link_libraries( native-lib app-glue ${log-lib} )
添加其他預構建庫:
include_directories( imported-lib/include/ )
add_library( imported-lib
SHARED
IMPORTED )
set_target_properties( # Specifies the target library.
imported-lib
# Specifies the parameter you want to define.
PROPERTIES IMPORTED_LOCATION
# Provides the path to the library you want to import.
imported-lib/src/${ANDROID_ABI}/libimported-lib.so )
- set_target_properties():命令指定庫的路徑,${ANDROID_ABI}添加庫的多個 ABI 版本的相對路徑。
- IMPORT:標記CMake將預構建庫導入項目中;
- include_directories():定位構建庫的頭文件;
包含其他CMake項目:
# Sets lib_src_DIR to the path of the target CMake project.
set( lib_src_DIR ../gmath )
# Sets lib_build_DIR to the path of the desired output directory.
set( lib_build_DIR ../gmath/outputs )
file(MAKE_DIRECTORY ${lib_build_DIR})
# Adds the CMakeLists.txt file located in the specified directory
# as a build dependency.
add_subdirectory( # Specifies the directory of the CMakeLists.txt file.
${lib_src_DIR}
# Specifies the directory for the build outputs.
${lib_build_DIR} )
# Adds the output of the additional CMake build as a prebuilt static
# library and names it lib_gmath.
add_library( lib_gmath STATIC IMPORTED )
set_target_properties( lib_gmath PROPERTIES IMPORTED_LOCATION
${lib_build_DIR}/${ANDROID_ABI}/lib_gmath.a )
include_directories( ${lib_src_DIR}/include )
# Links the top-level CMake build output against lib_gmath.
target_link_libraries( native-lib ... lib_gmath )
要構建多個 CMake 項目並在 Android 項目中包含它們的輸出,可以使用一個CMakeLists.txt
個作爲頂級CMake構建腳本,加其他 CMake 項目作爲此構建腳本的依賴項;
- add_subdirectory():將另一個
CMakeLists.txt
文件指定爲構建依賴項,然後關聯其輸出。
3.Java原生接口(JNI):