前段時間寫了篇Android Studio 第一個NDK例子,它是在使用
Android Studio2.1
版本的實現方案,最近發現2.2
穩定版本已經出來了,因此更新了版本,發現使用該版本建立Jni項目更加方便了。html
點擊File — New — New Project,把Include C++ Support
前面的CheckBook勾上。android
接下來的步驟跟建立普通項目同樣。app
在Customize C++ Support界面默認便可。ide
C++ Standard
指定編譯庫的環境,其中Toolchain Default使用的是默認的CMake環境;C++ 11也就是C++環境。兩種環境均可以編庫,至於區別,後續會跟進,當前博文使用的是CMake環境。函數
Exceptions Support
若是選中複選框,則表示當前項目支持C++異常處理,若是支持,在項目Module級別的build.gradle
文件中會增長一個標識 -fexceptions
到cppFlags
屬性中,而且在so庫構建時,gradle會把該屬性值傳遞給CMake進行構建。gradle
Runtime Type Information Support
同理,選中複選框,項目支持RTTI,屬性cppFlags
增長標識-frtti
ui
CMakeLists.txt文件用於配置JNI項目屬性,主要用於聲明CMake使用版本、so庫名稱、C/CPP文件路徑等信息,下面是該文件內容:spa
# Sets the minimum version of CMake required to build the native # library. You should either keep the default value or only pass a # value of 3.4.0 or lower. cmake_minimum_required(VERSION 3.4.1) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds it for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. native-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). # Associated headers in the same location as their source # file are automatically included. src/main/cpp/native-lib.cpp ) # Searches for a specified prebuilt library and stores the path as a # variable. Because system libraries are included in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in the # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. native-lib # Links the target library to the log library # included in the NDK. ${log-lib} )
cmake_minimum_required(VERSION 3.4.1)
CMake最小版本使用的是3.4.1。插件
add_library()
配置so庫信息(爲當前當前腳本文件添加庫)debug
intermediates\transforms\mergeJniLibs\debug\folders\2000\1f\main
下會生成相應的so庫文件。SHARED
這個參數表示共享so庫文件,也就是在Run項目或者build項目時會在目錄intermediates\transforms\mergeJniLibs\debug\folders\2000\1f\main
下生成so庫文。此外,so庫文件都會在打包到.apk裏面,能夠經過選擇菜單欄的Build->Analyze Apk...*查看apk中是否存在so庫文件,通常它會存放在lib目錄下。
src/main/cpp/native-lib.cpp
構建so庫的源文件。
STATIC:靜態庫,是目標文件的歸檔文件,在連接其它目標的時候使用。
SHARED:動態庫,會被動態連接,在運行時被加載。
MODULE:模塊庫,是不會被連接到其它目標中的插件,可是可能會在運行時使用dlopen-系列的函數動態連接。
更詳細的解釋請參考這篇文章:C++靜態庫與動態庫
下面的配置實際上與自定義的JNI項目(自定義的so庫)沒有太大關係。
find_library()
這個方法與咱們要建立的so庫無關而是使用NDK的Apis或者庫,默認狀況下Android平臺集成了不少NDK庫文件,因此這些文件是沒有必要打包到apk裏面去的。直接聲明想要使用的庫名稱便可(猜想:貌似是在Sytem/libs目錄下)。在這裏不須要指定庫的路徑,由於這個路徑已是CMake路徑搜索的一部分。如示例中使用的是log相關的so庫。
log-lib
這個指定的是在NDK庫中每一個類型的庫會存放一個特定的位置,而log庫存放在log-lib中
log
指定使用log庫
target_link_libraries()
若是你本地的庫(native-lib)想要調用log庫的方法,那麼就須要配置這個屬性,意思是把NDK庫關聯到本地庫。
native-lib
要被關聯的庫名稱
${log-lib}
要關聯的庫名稱,要用大括號包裹,前面還要有$符號去引用。
實際上,咱們能夠本身建立CMakeLists.txt文件,並且路徑不受限制,只要在build.gradle中配置externalNativeBuild.cmake.path來指定該文件路徑便可。
當Run或者Build項目時,想要執行CMakeLists.txt構建腳本,須要把腳本配置到模塊級的build.gradle中。
android { externalNativeBuild { cmake { path "CMakeLists.txt" } } }
實際上NDK除了有預置的庫還有一個源代碼(c/cpp),若是本地庫想要關聯這些代碼能夠這樣作:
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} )
app-glue
仍然是自定義庫的名稱
ANDROID_NDK
這個是Android Studio已經定義好的變量,能夠直接使用它指定的是NDK源代碼的根目錄。
在一些狀況下,咱們沒有能力開發so庫,當別人拋一個庫過來的時候咱們直接使用就行了。
首先,咱們告訴腳本咱們只須要導入so庫,不須要構建操做。
add_library( imported-lib SHARED IMPORTED )
接着,咱們要設置so庫的路徑了
set_target_properties(target1 target2 ... PROPERTIES prop1 value1 prop2 value2 ...)
舉例:
set_target_properties( imported-lib // so庫的名稱 PROPERTIES IMPORTED_LOCATION // import so庫 libs/libimported-lib.so // so庫路徑 )
當使用已經存在so庫時,不該該配置
target_link_libraries()
方法,由於只有在build 庫文件時才能進行link操做。
拓展閱讀:https://developer.android.com/ndk/guides/build.html
做者:科大向陽 連接:https://www.jianshu.com/p/4eefb16d83e3 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。