NDK學習( 二),在NDK開發中引入第三方庫(AndroidStudio Cmake)
阿新 • • 發佈:2019-01-09
在NDK中可能需要複用之前已經編譯好的so檔案,所以本章的目標是給一個之前編譯好的so檔案外加一個需要呼叫介面的標頭檔案,在現在專案中複用。
在本次實踐過程中,已經有編譯完成的各種cpu架構的libstringutil-lib.so以及標頭檔案,Stringutil.h
標頭檔案中簡單定義了兩個介面:
class StringUtil {
public:
static char* toLower(char* chars);
static char* toUpper(char* chars);
};
顧名思義上述介面已在libstringutil-lib.so中實現
現有工程需要呼叫這些介面,步驟如下:
1、在java層建立native介面
2、由Android Studio自動生成native層介面定義,native-lib是實現介面的cpp檔案:
此時編譯器應該找不到StringUtil的定義,因此需要將Stringutil.h拷貝到cpp檔案所在的資料夾下,本工程中如圖所示,新建一個include資料夾,將標頭檔案拷貝過去: 然後在native-lib.cpp中加入標頭檔案的引用:
3、將所有so檔案拷貝到工程的libs/jni目錄下
4、修改app下的gradle檔案,在android{}中加入如下程式碼,將so檔案作為引用
5、下面是最為關鍵的CmakeLists.txt的配置
6、測試程式碼 總結 最為關鍵的兩個步驟 1、在gradlle中指定本地的jni相對路徑 2、在CmakeLists.txt中指定加入編譯的so及其絕對路徑 #動態方式載入 stringutil-lib是libxxxx.so的xxxx部分 add_library(stringutil-lib SHARED IMPORTED) #設定要連線的so的相對路徑,${ANDROID_ABI}表示so檔案的ABI型別的路徑,這一步引入了動態加入編譯的so set_target_properties(stringutil-lib PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/jni/${ANDROID_ABI}/libstringutil-lib.so) #這裡多出了引用的stringutil-lib target_link_libraries( native-lib stringutil-lib ${log-lib} ) 由於時間不多,未調試出在CmakeLists.txt 中使用相對路徑的辦法,我在編譯中總是報找不到so的錯誤。有任何問題歡迎交流。 參考:
package dev.mars.jnidemo; public class StringUtils { static { System.loadLibrary("native-lib"); } public static native String toLower(String str); public static native String toUpper(String str); }
2、由Android Studio自動生成native層介面定義,native-lib是實現介面的cpp檔案:
extern "C" { JNIEXPORTjstring JNICALL Java_dev_mars_jnidemo_StringUtils_toLower(JNIEnv *env, jclass type, jstring str_) { const char *str = env->GetStringUTFChars(str_, 0); char* str2 =new char[strlen(str)]; strcpy(str2,str); StringUtil::toLower(str2); return env->NewStringUTF(str2); } JNIEXPORT jstring JNICALLJava_dev_mars_jnidemo_StringUtils_toUpper(JNIEnv *env, jclass type, jstring str_) { const char *str = env->GetStringUTFChars(str_, 0); char* str2 =new char[strlen(str)]; strcpy(str2,str); StringUtil::toUpper(str2); return env->NewStringUTF(str2); }
}
此時編譯器應該找不到StringUtil的定義,因此需要將Stringutil.h拷貝到cpp檔案所在的資料夾下,本工程中如圖所示,新建一個include資料夾,將標頭檔案拷貝過去: 然後在native-lib.cpp中加入標頭檔案的引用:
#include <string> #include <android/log.h> #include "include/StringUtil.h"
3、將所有so檔案拷貝到工程的libs/jni目錄下
4、修改app下的gradle檔案,在android{}中加入如下程式碼,將so檔案作為引用
sourceSets { main { jniLibs.srcDirs = ['./libs/jni'] } }
5、下面是最為關鍵的CmakeLists.txt的配置
cmake_minimum_required(VERSION 3.4.1) #定義變數ProjectRoot為工程根目錄,用相對路徑沒通過編譯,可能是路徑寫錯,以後再試 #本次使用絕對路徑作為引數 set(ProjectRoot G:/AndroidStudioProjects/JNIDemo) #將native-lib加入到編譯源中 add_library( native-lib SHARED src/main/jni/native-lib.cpp ) #動態方式載入 stringutil-lib是libxxxx.so的xxxx部分 add_library(stringutil-lib SHARED IMPORTED) #設定要連線的so的相對路徑,${ANDROID_ABI}表示so檔案的ABI型別的路徑,這一步引入了動態加入編譯的so set_target_properties(stringutil-lib PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/jni/${ANDROID_ABI}/libstringutil-lib.so) find_library( log-lib log ) #配置載入native依賴 #include_directories( ${ProjectRoot}/app/src/main/jni/include ) #這裡多出了引用的stringutil-lib target_link_libraries( native-lib stringutil-lib ${log-lib} )
6、測試程式碼 總結 最為關鍵的兩個步驟 1、在gradlle中指定本地的jni相對路徑 2、在CmakeLists.txt中指定加入編譯的so及其絕對路徑 #動態方式載入 stringutil-lib是libxxxx.so的xxxx部分 add_library(stringutil-lib SHARED IMPORTED) #設定要連線的so的相對路徑,${ANDROID_ABI}表示so檔案的ABI型別的路徑,這一步引入了動態加入編譯的so set_target_properties(stringutil-lib PROPERTIES IMPORTED_LOCATION ${ProjectRoot}/app/libs/jni/${ANDROID_ABI}/libstringutil-lib.so) #這裡多出了引用的stringutil-lib target_link_libraries( native-lib stringutil-lib ${log-lib} ) 由於時間不多,未調試出在CmakeLists.txt 中使用相對路徑的辦法,我在編譯中總是報找不到so的錯誤。有任何問題歡迎交流。 參考: