說明:本文相當於官方文檔的個人重新實現,官方文檔鏈接:https://developer.android.com/studio/projects/add-native-code
向項目添加C/C++代碼分為兩種情況,一種是創建支持C/C++代碼的新項目,一種是向原先不支持C/C++的已有項目添加C/C++代碼。這兩種情況分別對應本教程的第一大點和第二大點。
一、創建支持C/C++原生代碼的新項目教程
1.1、下載NDK和構建工具
要為應用編譯和調試原生代碼,需要安裝以下組件:
Android原生開發工具包 (NDK)----這套工具集允許我們為Android使用C和C++代碼,且其提供眾多平台庫讓我們可以管理原生Activity和訪問物理設備組件,例如傳感器和觸摸輸入。
CMake----一款外部構建工具,可與Gradle搭配使用來構建原生庫。如果只計划使用ndk-build,則不需要此組件。
LLDB----一種調試程序,Android Studio使用它來調試原生代碼。
安裝步驟如下:
菜單欄----Tools----SDK Manager
SDK Tools----鈎選CMake/LLDB/NDK三項----點擊確定
文件比較大,大概需要一二十分鍾(受網速影響),完成后點擊“Finish”即可
1.2、創建支持C/C++的新項目
菜單欄--File---new---New Project
其他信息按自己的需要填,主要是鈎選“Include C++ support”
接下來的三步和正常的項目創建沒什么區,按自己的需要鈎選或填寫即可。我這里演示使用,全直接使用默認配置。
在向導最后“Customize C++ Support”會有以下幾項內容:
C++ Standard----使用下拉列表選擇您希望使用哪種 C++ 標准。選擇 Toolchain Default 會使用默認的 CMake 設置。
Exceptions Support----如果您希望啟用對 C++ 異常處理的支持,請選中此復選框。如果啟用此復選框,Android Studio 會將 -fexceptions 標志添加到模塊級 build.gradle 文件的 cppFlags 中,Gradle 會將其傳遞到 CMake。
Runtime Type Information Support----如果您希望支持 RTTI,請選中此復選框。如果啟用此復選框,Android Studio 會將 -frtti 標志添加到模塊級 build.gradle 文件的 cppFlags 中,Gradle 會將其傳遞到 CMake。
我這里使用默認配置,直接點擊“Finish”
1.3、確認程序可以成功調用C++函數
將項目切換到“Android”視圖觀察整個項目,可發現較沒有“Include C++ support”的項目,多了cpp和External Build Files兩個組
在設計中cpp組用於存放項目的所有原生源文件、標頭和預構建庫。對於當前項目,Android Studio只創建了一個名為native-lib.cpp的C++源文件(位於src/main/cpp/目錄)其中只有一個簡單的C++函數stringFromJNI(),該函數返回字符串“Hello from C++”。
External Build Files組用於存放CMake或ndk-build的構建腳本。與Gradle需要build.gradle文件來指示如何構建應用一樣,CMake和ndk-build依照一個構建腳本來構建原生庫。對於當前項目,Android Studio創建了一個CMake構建腳本CMakeLists.txt(位於模塊的根目錄),用於指示編譯構建native-lib.cpp。
點擊查看“native-lib.cpp”內容如下,只有一個返回“Hello from C++”的函數
查看生成的activity_main.xml,如容如下,和Android Studio正常默認生成的項目一樣,只有一個顯示“Hello World!”的文本框
查看MainActivity.java內容如下,首選使用了System.loadLibrary()加載了本地庫,然后在onCreate()中將activity_main.xml中的文框的內容修改為原生函數stringFromJNI()返回的字符串(Hello from C++)
我們直接在模擬器上運行app,如果界面文本框顯示的不是“Hello World!”而是“Hello from C++”那說明程序成功調用原生函數。
菜單欄----Run----Run ‘app’選擇虛擬機運行
圖中的”Nexus 5X API 28”是我之前創建的虛擬機,沒有虛擬機點擊左下方的“Create New Virtual Device”創建即可。
可以看到界面如下,確實顯示的是“Hello from C++”,也就是說經過如此配置之后程序確實可以成功調用C++函數
1.4 創建新的原生源文件【可選】
如果是簡單使用,那直接在上邊的native-lib.cpp后邊追加函數即可(不過要注意前邊的extern "C" JNIEXPORT jstring JNICALL相當於jstring,用於指明函數的返回值類型,自己在添加新函數時不要忘了需要指明返回值類型這回事,以致函數名位置一直報“Cannot resolve type”錯誤),在實際使用中經常需要創建多個文件。下邊介紹如何創建新的原生源文件。
1.4.1 創建新的原生源文件
切換到“Project”視圖,定位到app--src-main--cpp,在其上右鍵New--C/C++ Source File
這里我創建一個native-test.cpp
然后將native-lib.cpp中的函數復制過來,修改一下函數名和返回的字符串
1.4.2 修改CMake構建腳本
構建腳本只能有一個,而且名字必須為CMakeLists.txt,我們在Project視圖app根目錄下找到CMakeLists.txt。
模仿書寫add_library()指出要生成的lib名及對應的源文件
接下來修改MainActivity.java將默認生成的調用stringFromJNI()改為調用我們修改過的stringFromJNITest()
程序成功安裝運行,顯示字符串也確實為"native-test:Hello from C++",證明成功調用
二、向已有項目添加添加C/C++代碼
首先要明確,“為已有項目添加添加C/C++代碼”其實質就要將“創建支持C/C++原生代碼的新項目”中IDE自動為做好的步驟手動去實現。
C/C++原生代碼支持在Android Studio中就是以下四步:第一步,安裝CMake/LLDB/NDK。第二步,在項目中創建原生源文件。第三步,創建和編寫CMake構建腳本CMakeLists.txt。第四步,向Gradle注冊構建請求。
手動實現時照葫蘆畫標即可。
2.1 安裝CMake/LLDB/NDK
與前邊1.1節一樣,不再贅述。
2.2 在項目中創建原生源文件
寫入一個測試函數(這個函數就是“創建支持C/C++原生代碼的新項目”時默認生成的函數,借過來用即可。不過千萬要注意函數名前的包名要改成自己當前的包名,不然在java中調用就報找不到函數了)
#include <jni.h> #include <string> extern "C" JNIEXPORT jstring JNICALL Java_com_example_ls_test1_Main1Activity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); }
2.3 創建和編寫CMake構建腳本CMakeLists.txt
寫入以下內容(這里“創建支持C/C++原生代碼的新項目”時自動生成的內容,find_library和target_link_libraries還不很清楚什么用但全復制進去准沒錯)
cmake_minimum_required(VERSION 3.4.1) 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). src/main/cpp/native-lib.cpp ) 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 ) target_link_libraries( # Specifies the target library. native-lib # Links the target library to the log library # included in the NDK. ${log-lib} )
2.4 向Gradle注冊構建請求
打開build.gradle向android/defaultConfig節區追加以下內容:
externalNativeBuild { cmake { cppFlags "" } }
向android節區追加以下內容:
externalNativeBuild { cmake { path "CMakeLists.txt" } }
2.5 確認程序可以成功調用C++函數
這個和1.3一樣然證即可,我自己測試結果和1.3一樣是可以成功調用的。