聲明:該文章我是之前查網上別的大神的,至於到底是誰,我也不知道了,發表出來我沒有其他的意思,就是爲了方便自己以後快速查閱。不存在騙流量說法,我的所有文章都是。只是爲了自己方便,畢竟存在電腦裏,還需要電腦或者U盤。在CSDN上,特殊環境下手機都可以看了。
一、創建支持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”
其他信息按自己的需要填,主要是鉤選“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名及對應的源文件
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# 限定cmake支持最低版本
cmake_minimum_required(VERSION 3.4.1)
# 指定so生成到libs目錄
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI})
# 配置so庫的信息
add_library( # Sets the name of the library.
# 生成的so庫名稱,並不需要和c/cpp文件名相同
# 這裏生產的so庫名稱將爲libnative-lib.so
native-lib
# Sets the library as a shared library.
# STATIC:靜態庫,是目標文件的歸檔文件,在鏈接其它目標的時候使用
# SHARED:動態庫,會被動態鏈接,在運行時被加載
# MODULE:模塊庫,是不會被鏈接到其它目標中的插件,但是可能會在運行時使用dlopen-系列的函數動態鏈接
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依賴庫
# {sdk-path}/ndk-bundle/sysroot/usr/include/android/log.h
log )
# 配置庫的依賴關係(鏈接關係)
target_link_libraries( # Specifies the target library.
# 目標庫
native-lib
# Links the target library to the log library
# included in the NDK.
# 依賴庫,可以是多個
${log-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一樣是可以成功調用的。