在 Android Studio 2.2 中愉快地使用 C/C++
2019獨角獸企業重金招聘Python工程師標準>>>
?Android Studio 2.2 正式版發布后,看到更新內容中有提到對 C/C++ 支持的完善,表示非常高興。然后將官網上這一部分內容翻譯出來,如有錯誤,歡迎指正。
原文鏈接:Add C and C++ Code to Your Project
使用 Android studio,你可以將 C 和 C++ 代碼構建成 native library(即 .so 文件),然后打包到你的 APK 中。你的?Java?代碼可以通過?Java?Native Interface(JNI)調用 native library 庫中的方法。
Android Studio 默認使用 CMake 編譯原生庫。由于已經有大量的代碼使用了 ndk-build 來編譯 native code,所以 Android Studio 同樣也支持 ndk build。如果你想導入一個 ndk-build 庫到你的 Android Studio 項目中,請參閱后文的?關聯本地庫與 Gradle?部分。然而,如果你創建了一個新的 native 庫工程,你應該使用 CMake。
本篇文章將會說明如何使用 Android Studio 來創建、配置 Android 項目,以支持 native code,以及將其運行到你的 app 中。
注意:要在 Android Studio 中使用 CMake 或者 ndk-build,你需要使用 Android Studio 2.2 或更高的版本,同時需要配合使用 Android Plugin for Gradle 2.2.0 及以上的版本。
下載 NDK 和構建工具
要編譯和調試本地代碼(native code),你需要下面的組件:
- The Android Native Development Kit (NDK): 讓你能在 Android 上面使用 C 和 C++ 代碼的工具集。
- CMake: 外部構建工具。如果你準備只使用 ndk-build 的話,可以不使用它。
- LLDB: Android Studio 上面調試本地代碼的工具。
你可以使用 SDK Manager 來安裝上述組件:
?創建支持 C/C++ 的新項目
創建一個支持 native code 的項目和創建普通的 Android studio 工程很像。但是有幾點需要留意的地方:
在?Customize C++ Support?選項卡中。你有下面幾種方式來自定義你的項目:
- C++ Standard:點擊下拉框,可以選擇標準 C++,或者選擇默認 CMake 設置的?Toolchain Default?選項。
- Exceptions Support:如果你想使用有關 C++ 異常處理的支持,就勾選它。勾選之后,Android Studio 會在 module 層的 build.gradle 文件中的?cppFlags?中添加?-fexcetions?標志。
- Runtime Type Information Support:如果你想支持 RTTI,那么就勾選它。勾選之后,Android Studio 會在 module 層的 build.gradle 文件中的?cppFlags?中添加?-frtti?標志。
當 Android Studio 完成新項目創建后,打開?Project?面板,選擇?Android?視圖。Android Studio 會添加?cpp?和?External Build Files?目錄。
編譯運行示例 APP
當你點擊?Run?按鈕,Android Studio 會編譯并啟動一個 APP ,然后在 APP 中顯示一段文字”Hello from C++”。從編譯到運行示例 APP 的流程簡單歸納如下:
注意:Instant Run?并不兼容使用了 native code 的項目。Android Studio 會自動禁止?Instant Run?功能。
如果你想驗證一下 Gradle 是否將 native library 打包進了 APK,你可以使用 APK Analyzer:
?
將 C/C++ 代碼添加到現有的項目中
如果你想將 native code 添加到一個現有的項目中,請按照下面的步驟操作:
一旦你配置好了項目,你就可以在 Java 代碼中,使用 JNI 框架開調用原生函數(native functions)。只需要點擊?Run?按鈕,就可以編譯運行你的 APP 了。
創建新的 native source 文件
請按照下面的方法來創建一個?cpp/?目錄和源文件(native source files):
?創建 CMake 構建腳本
如果沒有一個 CMake 構建腳本,你需要自己手動創建一個,并添加一些合適的 CMake 命令。CMake 構建腳本是一個空白的文本文檔(后綴為 .txt 的文件),名字必須為?CMakeLists.txt。
注意:如果你的項目使用了 ndk-build,你就不需要創建 CMake 構建腳本,只需要提供一個路徑鏈,將你的 Android.mk 文件鏈接到 Gradle 中即可。
將一個空白的文本文檔變成一個 CMake 構建腳本,你需要這么做:
現在,你可以添加 CMake 命令來配置你的構建腳本了。為了讓 CMake 將源代碼(native source code)編譯成 native library。需要在編譯文件中添加?cmake_minimum_required()?和?add_library()?命令:
# 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 )當你使用?add_library(),將一個源文件(source file)或庫添加到你的 CMake 構建腳本,同步你的項目,然后你會發現 Android studio 將關聯的頭文件也顯示了處理。然而,為了讓 CMake 在編譯時期能定位到你的頭文件,你需要在 CMake 構建腳本中添加?include_directories()?命令,并指定頭文件路徑:
add_library(...)# Specifies a path to native header files. include_directories(src/main/cpp/include/)然后,按照約定,CMake 會將生成的 library 命名為下面的形式:
lib*library-name*.so
比如,如果你在構建腳本中,將 library 命名為 “native-lib”,那么 CMake 會創建叫?libnative-lib.so?的文件。但是,當你將 library 加載到 Java 代碼中的時候, 你需要使用在 CMake 中指定的名稱:
static {System.loadLibrary(“native-lib”); }注意:如果你將 CMake 腳本里面的 library 重命名了,或者移除了。你需要清理一下你的工程。在 IDE 的菜單欄中選擇?Build > Clean Project。
Android Studio 會在 Project 面板中的 cpp 目錄中自動添加源文件和頭文件。你可以多次使用?add_library()?命令,來添加額外的 library。
添加 NDK APIs
Android NDK 提供了一些有用的 native APIs。將 NDK librarys 添加到 CMakeLists.txt 腳本文件中,就可以使用這些 API 了。
預編譯的 NDK librarys 已經存在在 Android 平臺中了,所以你不需要編譯它們,或者是將其打包到你的 APK 中。因為這些 NDK librarys 已經是 CMake 搜索路徑的一部分,你甚至不需要提供你本地安裝的 NDK 路徑。你只需要向 CMake 提供你想使用的 library 名字。
將?find_library()?命令添加到你的 CMake 構建腳本中,這樣就可以定位 NDK library 的位置,并將其位置存儲在一個變量之中。你可以在構建腳本的其他地方使用這個變量,來代指 NDK library。下面的示例代碼將?Android-specific log support library?的位置存儲到變量?log-lib?中:
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 )NDK 同樣也包含一些只包含源碼的 library,這些就需要你去編譯,然后鏈接到你的本地庫(native library)。你可以在 CMake 構建腳本中使用?add_library()?命令將源碼編譯進本地庫。這時就需要提供你的本地 NDK 安裝路徑,通常將該路徑保存在?ANDROID_NDK?變量中,這樣 Android Studio 可以自動為你識別。
下面的命令告訴 CMake 去構建?android_native_app_glue.c,這個命令可以管理?NativeActivity?的生命周期以及點擊輸入,并將其導入靜態庫中,然后將其鏈接至?native-lib:
add_library( app-glueSTATIC${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} )添加其他的預編譯庫
添加預編譯庫和添加本地庫(native library)類似。由于預編譯庫是已經構建好的,你想就要使用?IMPORTED?標志去告訴 CMake ,你只需要將其導入到你的項目中即可:
add_library( imported-libSHAREDIMPORTED )然后你需要使用?set_target_properties()?命令去指定庫的路徑,就像下面的代碼那樣。
一些庫會根據不同的 CPU 使用不同的包,或者是?Application Binary Interfaces(ABI),并且將他們歸類到不同的目錄中。這樣做的好處是,可以充分發揮特定的 CPU?架構。你可以使用?ANDROID_ABI?路徑變量,將多個 ABI 版本的庫添加到你的 CMake 構建腳本中。這個變量使用了一些 NDK 默認支持的 ABI,以及一些需要手動配置到 Gradle 的 ABI,比如:
add_library(...) 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 )為了讓 CMake 在編譯時期能找到你的頭文件,你需要使用?include_directories()?命令,并且將你的頭文件地址傳進去:
include_directories( imported-lib/include/ )在 CMake 構建腳本中使用?target_link_libraries()?命令,將預構建庫與你本地庫相關聯:
target_link_libraries( native-lib imported-lib app-glue ${log-lib} )當你構建你的 APP 的時候,Gradle 會自動將導入的庫打包到你的 APK 中。你可以使用 APK Analyzer 來檢查。
關聯本地庫與 Gradle
為了將本地庫與 Gradle 相關聯,你需要在 CMake 或 ndk-build 構建腳本中提供一個路徑地址。當你構建你的 APP 時,Gradle 會將 CMake 或 ndk-build 作為一個依賴運行,然后將共享庫(.so 文件)打包到你的 APK 中。Gradle 同樣使用構建腳本來識別哪些文件需要導入到 Android Studio 項目,你可以從?Project?窗口面板中看到相應的文件。如果你還沒有一個為 native sources 準備的構建腳本,你需要先創建一個。
使用 Android Studio 圖形化界面
你可以使用 Android Studio 的圖形化界面來將 Gradle 與外部 CMake 或者 ndk-build 項目關聯起來。
在下拉菜單中,選擇?CMake?或者?ndk-build。?
a. 如果你選擇?CMake,需要在?Project Path?中指定?CMakeLists.txt?腳本文件的路徑。?
b. 如果你選擇?ndk-build,你需要在?Project Path?中指定?Android.mk?腳本文件的路徑。
點擊?OK。
?
手動配置 Gradle
如果要手動將 Gradle 與你的本地庫相關聯,你需要在 module 層級的 build.gradle 文件中添加?externalNativeBuild {}?代碼塊,并且在該代碼塊中配置?cmake {}?或?ndkBuild {}:
android {...defaultConfig {...}buildTypes {...}// Encapsulates your external native build configurations.externalNativeBuild {// Encapsulates your CMake build configurations.cmake {// Provides a relative path to your CMake build script.path "CMakeLists.txt"}} }可選配置
你可以在你的 module 層級的 build.gradle 文件中的?defaultConfig {}?代碼塊中,添加?externalNativeBuild {}?代碼塊,為 CMake 或 ndk-build 配置一些額外參數。當然,你也可以在你的構建配置中的其他每一個生產渠道重寫這些屬性。
比如,如果你的 CMake 或者 ndk-build 項目中定義了多個本地庫,你想在某個生產渠道使用這些本地庫中的幾個,你就可以使用?targets?屬性來構建和打包。下面的代碼展示了一些你可能會用到的屬性:
android {...defaultConfig {...// This block is different from the one you use to link Gradle// to your CMake or ndk-build script.externalNativeBuild {// For ndk-build, instead use ndkBuild {}cmake {// Passes optional arguments to CMake.arguments "-DCMAKE_VERBOSE_MAKEFILE=TRUE"// Sets optional flags for the C compiler.cFlags "-D_EXAMPLE_C_FLAG1", "-D_EXAMPLE_C_FLAG2"// Sets a flag to enable format macro constants for the C++ compiler.cppFlags "-D__STDC_FORMAT_MACROS"}}}buildTypes {...}productFlavors {...demo {...externalNativeBuild {cmake {...// Specifies which native libraries to build and package for this// product flavor. If you don't configure this property, Gradle// builds and packages all shared object libraries that you define// in your CMake or ndk-build project.targets "native-lib-demo"}}}paid {...externalNativeBuild {cmake {...targets "native-lib-paid"}}}}// You use this block to link Gradle to your CMake or ndk-build script.externalNativeBuild {cmake {...}// or ndkBuild {...}} }指定 ABI
一般情況下,Gradle 會將你的本地庫構建成?.so?文件,然后將其打包到你的 APK 中。如果你想 Gradle 構建并打包某個特定的 ABI 。你可以在你的 module 層級的 build.gradle 文件中使用?ndk.abiFilters?標簽來指定他們:
android {...defaultConfig {...externalNativeBuild {cmake {...}// or ndkBuild {...}}ndk {// Specifies the ABI configurations of your native// libraries Gradle should build and package with your APK.abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a','arm64-v8a'}}buildTypes {...}externalNativeBuild {...} }大多數情況,你只需要像上面的代碼那樣,在?ndk {}?代碼塊中指定?abiFilters?即可。如果你想控制 Gradle 構建、依賴你希望的東西,你就需要在?defaultConfig.externalNativeBuild.cmake {}?代碼塊或?defaultConfig.externalNativeBuild.ndkBuild {}?代碼塊中,配置其他的?abiFilters?標簽。Gradle 會構建這些 ABI 配置,但是只會將?defaultConfig.ndk {}?代碼塊中指定的東西打包到 APk 中。
轉載于:https://my.oschina.net/u/735973/blog/812920
總結
以上是生活随笔為你收集整理的在 Android Studio 2.2 中愉快地使用 C/C++的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu14.04安装redis和简
- 下一篇: MYSQL管理之主从同步管理