【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )
文章目錄
- I . Android Studio 中使用 Android.mk 配置動(dòng)態(tài)庫(kù) 總結(jié)
- II . 第三方動(dòng)態(tài)庫(kù)來(lái)源
- III . 配置 Android.mk 構(gòu)建腳本路徑
- IV . 預(yù)編譯 第三方 動(dòng)態(tài)庫(kù) ( Android.mk )
- V . 鏈接動(dòng)態(tài)庫(kù) ( 設(shè)置動(dòng)態(tài)庫(kù)依賴 )
- VI . Java 代碼定義 native 方法并加載動(dòng)態(tài)庫(kù)
- VII . C 代碼調(diào)用動(dòng)態(tài)庫(kù)函數(shù)
- VIII . 動(dòng)態(tài)庫(kù)加載版本限制 ( 6.0 以上 不能使用 Android.mk 配置動(dòng)態(tài)庫(kù) )
- IX . 完整代碼示例
- 1 . build.gradle 配置示例
- 2 . Android.mk 配置示例
- 3 . Java 代碼示例
- 4 . C 代碼示例
- 5 . 運(yùn)行結(jié)果 ( Android 4.3 手機(jī) | 6.0 以上系統(tǒng)無(wú)法運(yùn)行 )
- X . 博客資源
I . Android Studio 中使用 Android.mk 配置動(dòng)態(tài)庫(kù) 總結(jié)
Android Studio 中使用 Android.mk 配置第三方 動(dòng)態(tài)庫(kù) :
① Android.mk 腳本路徑設(shè)置 : 在 Module 級(jí)別的 build.gradle 腳本中配置 Android.mk 構(gòu)建腳本的路徑 ;
externalNativeBuild {ndkBuild{path "src/main/ndkBuild_Shared/Android.mk"}}② 預(yù)編譯第三方動(dòng)態(tài)庫(kù) : 在 Android.mk 中預(yù)編譯動(dòng)態(tài)庫(kù) , 注意動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)使用的配置不同 , 這里以動(dòng)態(tài)庫(kù)舉例 :
include $(CLEAR_VARS) LOCAL_MODULE := add LOCAL_SRC_FILES := libadd.so include $(PREBUILT_SHARED_LIBRARY)③ 鏈接動(dòng)態(tài)庫(kù) : 在 Android.mk 中預(yù)鏈接動(dòng)態(tài)庫(kù)或靜態(tài)庫(kù) , 注意動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)使用的配置不同 , 這里以動(dòng)態(tài)庫(kù)舉例 :
LOCAL_SHARED_LIBRARIES := add④ Java 代碼實(shí)現(xiàn) : 聲明 native 方法 , 加載編譯的動(dòng)態(tài)庫(kù) ;
⑤ C 代碼實(shí)現(xiàn) : 聲明函數(shù)庫(kù)中的函數(shù) , 調(diào)用動(dòng)態(tài)庫(kù)中的函數(shù) ;
II . 第三方動(dòng)態(tài)庫(kù)來(lái)源
1 . 第三方動(dòng)態(tài)庫(kù)源碼 : add.c ;
#include <stdio.h>int add(int a, int b){return a + b; }2 . Ubuntu 交叉編譯過(guò)程 : 參考 【Android NDK 開(kāi)發(fā)】Ubuntu 函數(shù)庫(kù)交叉編譯 ( Android 動(dòng)態(tài)庫(kù)交叉編譯 | Android 靜態(tài)庫(kù)交叉編譯 ) , 最終編譯出 libadd.so 動(dòng)態(tài)庫(kù) , 和 libadd.a 靜態(tài)庫(kù) ;
III . 配置 Android.mk 構(gòu)建腳本路徑
1 . 源碼 編譯 / 打包 配置 原理 : 【Android NDK 開(kāi)發(fā)】Android Studio 的 NDK 配置 ( 源碼編譯配置 | 構(gòu)建腳本配置 | 打包配置 | CMake 配置 | ndkBuild 配置 ) : I . 源碼編譯配置
2 . 構(gòu)建腳本路徑配置 原理 : 【Android NDK 開(kāi)發(fā)】Android Studio 的 NDK 配置 ( 源碼編譯配置 | 構(gòu)建腳本配置 | 打包配置 | CMake 配置 | ndkBuild 配置 ) : II . 構(gòu)建腳本配置
3 . 這里直接設(shè)置 Android.mk 構(gòu)建腳本路徑 : 省略無(wú)關(guān)配置 , 只保留 NDK 相關(guān)配置 ;
apply plugin: 'com.android.application'android {...defaultConfig {...// 配置 AS 工程中的 C/C++ 源文件的編譯// defaultConfig 內(nèi)部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數(shù)// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構(gòu)建腳本的路徑externalNativeBuild {/*cmake {cppFlags ""//配置編譯 C/C++ 源文件為哪幾個(gè) CPU 指令集的函數(shù)庫(kù) (arm , x86 等)abiFilters "armeabi-v7a"}*/ndkBuild{abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}//配置 APK 打包 哪些動(dòng)態(tài)庫(kù)// 示例 : 如在工程中集成了第三方庫(kù) , 其提供了 arm, x86, mips 等指令集的動(dòng)態(tài)庫(kù)// 那么為了控制打包后的應(yīng)用大小, 可以選擇性打包一些庫(kù) , 此處就是進(jìn)行該配置ndk{// 打包生成的 APK 文件指揮包含 ARM 指令集的動(dòng)態(tài)庫(kù)abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}// 配置 NDK 的編譯腳本路徑// 編譯腳本有兩種 ① CMakeList.txt ② Android1.mk// defaultConfig 內(nèi)部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數(shù)// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構(gòu)建腳本的路徑externalNativeBuild {// 配置 CMake 構(gòu)建腳本 CMakeLists.txt 腳本路徑/*cmake {path "src/main/cpp/CMakeLists.txt"version "3.10.2"}*/// 配置 Android1.mk 構(gòu)建腳本路徑ndkBuild{path "src/main/ndkBuild_Shared/Android.mk"//path "src/main/ndkBuild_Static/Android.mk"}}... } ...IV . 預(yù)編譯 第三方 動(dòng)態(tài)庫(kù) ( Android.mk )
1 . 清除變量 : ( add 模塊配置開(kāi)始 )
① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 ;
② 例外情況 : 有一個(gè)例外 , 就是不會(huì)清除 LOCAL_PATH 變量 ;
③ 模塊開(kāi)始標(biāo)識(shí) : include $(CLEAR_VARS) , 一般作為一個(gè)模塊配置的起始標(biāo)志 ;
④ 模塊結(jié)尾 : include $(XXX_STATIC_LIBRARY) / include $(XXX_SHARED_LIBRARY) 一般作為模塊配置結(jié)束標(biāo)志 ;
include $(CLEAR_VARS)2 . 配置動(dòng)態(tài)庫(kù)名稱 :
① 自動(dòng)生成函數(shù)庫(kù)名稱前提 : 沒(méi)有 LOCAL_MODULE_FILENAME 配置 , 就會(huì)自動(dòng)生成函數(shù)庫(kù)名稱 ;
② 動(dòng)態(tài)庫(kù)命名規(guī)則 : 在 LOCAL_MODULE 名稱基礎(chǔ)上 , 添加 lib 前綴 ( 如果前面有 lib 前綴不再添加 ) 和 .so 后綴 ;
③ 生成動(dòng)態(tài)庫(kù)名稱 : libadd.so ;
LOCAL_MODULE := add3 . 設(shè)置預(yù)編譯的動(dòng)態(tài)庫(kù)路徑 :
LOCAL_SRC_FILES := libadd.so4 . 設(shè)置預(yù)編譯動(dòng)態(tài)庫(kù) : ( add 模塊配置結(jié)束 )
include $(PREBUILT_SHARED_LIBRARY)5 . 完整的第三方動(dòng)態(tài)庫(kù)預(yù)編譯模塊配置 :
# II . 預(yù)編譯第三方動(dòng)態(tài)庫(kù)# 1 . 清除變量 ( add 模塊配置開(kāi)始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會(huì)清除 LOCAL_PATH 變量 # ③ 模塊開(kāi)始 : include $(CLEAR_VARS) # ④ 模塊結(jié)尾 : include $(XXX_STATIC_LIBRARY) / include $(XXX_SHARED_LIBRARY) include $(CLEAR_VARS)# 2 . 配置動(dòng)態(tài)庫(kù)名稱 # ① 自動(dòng)生成函數(shù)庫(kù)名稱前提 : 沒(méi)有 LOCAL_MODULE_FILENAME 配置 , 就會(huì)自動(dòng)生成函數(shù)庫(kù)名稱 # ② 動(dòng)態(tài)庫(kù)命名規(guī)則 : 在 LOCAL_MODULE 名稱基礎(chǔ)上 , 添加 lib 前綴和 .so 后綴 # ③ 生成動(dòng)態(tài)庫(kù)名稱 : libadd.so LOCAL_MODULE := add# 3 . 預(yù)編譯的動(dòng)態(tài)庫(kù)路徑 LOCAL_SRC_FILES := libadd.so# 4 . 設(shè)置預(yù)編譯動(dòng)態(tài)庫(kù) ( add 模塊配置結(jié)束 ) include $(PREBUILT_SHARED_LIBRARY)V . 鏈接動(dòng)態(tài)庫(kù) ( 設(shè)置動(dòng)態(tài)庫(kù)依賴 )
設(shè)置動(dòng)態(tài)依賴庫(kù) :
① 依賴庫(kù) : 編譯 native-lib 模塊 , 需要鏈接 add 靜態(tài)庫(kù) ;
② add 動(dòng)態(tài)庫(kù) : add 模塊是一個(gè)預(yù)編譯庫(kù) , 預(yù)編譯內(nèi)容是引入的第三方動(dòng)態(tài)庫(kù) ;
LOCAL_SHARED_LIBRARIES := add # IV . 配置動(dòng)態(tài)庫(kù)模塊# 1 . 清除變量 ( native-lib 模塊配置開(kāi)始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會(huì)清除 LOCAL_PATH 變量 include $(CLEAR_VARS)# 2 . 配置動(dòng)態(tài)庫(kù)名稱 # ① 自動(dòng)生成函數(shù)庫(kù)名稱前提 : 沒(méi)有 LOCAL_MODULE_FILENAME 配置 , 就會(huì)自動(dòng)生成函數(shù)庫(kù)名稱 # ② 動(dòng)態(tài)庫(kù)命名規(guī)則 : 在 LOCAL_MODULE 名稱基礎(chǔ)上 , 添加 lib 前綴 和 .so 后綴 # ③ 生成動(dòng)態(tài)庫(kù)名稱 : libnative-lib.so LOCAL_MODULE := native-lib# 3 . 編譯的源文件 LOCAL_SRC_FILES := native-lib.c# 4 . 設(shè)置動(dòng)態(tài)依賴庫(kù) # ① 依賴庫(kù) : 編譯 native-lib 模塊 , 需要鏈接 add 動(dòng)態(tài)庫(kù) # ② add 動(dòng)態(tài)庫(kù) : add 模塊是一個(gè)預(yù)編譯庫(kù) , 預(yù)編譯內(nèi)容是引入的第三方動(dòng)態(tài)庫(kù) LOCAL_SHARED_LIBRARIES := add# 5 . 鏈接日志庫(kù) LOCAL_LDLIBS := -llog# 6 . 設(shè)置預(yù)編譯動(dòng)態(tài)庫(kù) ( native-lib 模塊配置結(jié)束 ) include $(BUILD_SHARED_LIBRARY)VI . Java 代碼定義 native 方法并加載動(dòng)態(tài)庫(kù)
1 . 聲明 并使用 native 方法 :
public native String stringFromJNI();2 . 加載動(dòng)態(tài)庫(kù) : 這里要加載兩個(gè)動(dòng)態(tài)庫(kù) ;
System.loadLibrary("add");System.loadLibrary("native-lib");VII . C 代碼調(diào)用動(dòng)態(tài)庫(kù)函數(shù)
1 . 聲明動(dòng)態(tài)庫(kù)外部方法 :
//聲明 libadd.so 動(dòng)態(tài)庫(kù)中的方法 extern int add(int a, int b);2 . 調(diào)用動(dòng)態(tài)庫(kù)的方法 :
//調(diào)用動(dòng)態(tài)庫(kù)中的函數(shù) int sum = add(1, 2);VIII . 動(dòng)態(tài)庫(kù)加載版本限制 ( 6.0 以上 不能使用 Android.mk 配置動(dòng)態(tài)庫(kù) )
1 . 問(wèn)題描述 :
6.0 版本開(kāi)始 , 使用 Android.mk 構(gòu)建腳本預(yù)編譯第三方的動(dòng)態(tài)庫(kù) , 如果程序中使用 System.loadLibrary 加載該預(yù)編譯庫(kù) , 就會(huì)報(bào)錯(cuò) ;
6.0 以下的手機(jī)版本 ( 不包括 6.0 版本 ) , System.loadLibrary 需要手動(dòng)加載依賴的動(dòng)態(tài)庫(kù) ;
6.0 及以上的手機(jī)版本 , System.loadLibrary 會(huì)自動(dòng)加載依賴的動(dòng)態(tài)庫(kù) , 此時(shí)不能加載依賴的動(dòng)態(tài)庫(kù) , 否則會(huì)出錯(cuò) ;
2 . 報(bào)錯(cuò)信息 : 6.0 以上的手機(jī) 不能使用 Android.mk 加載動(dòng)態(tài)庫(kù) , 一旦加載崩潰 ; 報(bào)以下錯(cuò)誤 ;
2020-02-13 01:58:38.044 23033-23033/kim.hsl.mk E/AndroidRuntime: FATAL EXCEPTION: mainProcess: kim.hsl.mk, PID: 23033java.lang.UnsatisfiedLinkError: dlopen failed: library "Y:/002_WorkSpace/001_AS/006_NDK_Android_mk/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libadd.so" not foundat java.lang.Runtime.loadLibrary0(Runtime.java:977)at java.lang.System.loadLibrary(System.java:1567)at kim.hsl.mk.MainActivity.<clinit>(MainActivity.java:19)...3 . 解決方案 : 6.0 以上的手機(jī) , 只能使用 CMake 配置動(dòng)態(tài)庫(kù) , 或者使用靜態(tài)庫(kù) ;
4 . CMake 配置方案參考 : 【Android NDK 開(kāi)發(fā)】NDK 交叉編譯 ( Ubuntu 中交叉編譯動(dòng)態(tài)庫(kù) | Android Studio 中配置使用第三方動(dòng)態(tài)庫(kù) )
IX . 完整代碼示例
1 . build.gradle 配置示例
apply plugin: 'com.android.application'android {compileSdkVersion 29buildToolsVersion "29.0.0"defaultConfig {applicationId "kim.hsl.mk"minSdkVersion 15targetSdkVersion 29versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"// 配置 AS 工程中的 C/C++ 源文件的編譯// defaultConfig 內(nèi)部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數(shù)// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構(gòu)建腳本的路徑externalNativeBuild {/*cmake {cppFlags ""//配置編譯 C/C++ 源文件為哪幾個(gè) CPU 指令集的函數(shù)庫(kù) (arm , x86 等)abiFilters "armeabi-v7a"}*/ndkBuild{abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}//配置 APK 打包 哪些動(dòng)態(tài)庫(kù)// 示例 : 如在工程中集成了第三方庫(kù) , 其提供了 arm, x86, mips 等指令集的動(dòng)態(tài)庫(kù)// 那么為了控制打包后的應(yīng)用大小, 可以選擇性打包一些庫(kù) , 此處就是進(jìn)行該配置ndk{// 打包生成的 APK 文件指揮包含 ARM 指令集的動(dòng)態(tài)庫(kù)abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}// 配置 NDK 的編譯腳本路徑// 編譯腳本有兩種 ① CMakeList.txt ② Android1.mk// defaultConfig 內(nèi)部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數(shù)// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構(gòu)建腳本的路徑externalNativeBuild {// 配置 CMake 構(gòu)建腳本 CMakeLists.txt 腳本路徑/*cmake {path "src/main/cpp/CMakeLists.txt"version "3.10.2"}*/// 配置 Android1.mk 構(gòu)建腳本路徑ndkBuild{path "src/main/ndkBuild_Shared/Android.mk"//path "src/main/ndkBuild_Static/Android.mk"}}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}} }dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])implementation 'androidx.appcompat:appcompat:1.1.0'implementation 'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation 'junit:junit:4.12'androidTestImplementation 'androidx.test:runner:1.2.0'androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' }
2 . Android.mk 配置示例
# I . 保存構(gòu)建腳本的路徑 , 并賦值給 LOCAL_PATH 變量# ① 內(nèi)置函數(shù) : my-dir 是 NDK 內(nèi)置的函數(shù) , 獲取當(dāng)前的目錄路徑 # 在該案例中就是 Android.mk 文件所在的目錄的絕對(duì)路徑 , 工程根目錄/app/src/main/cpp # 將該目錄賦值給 LOCAL_PATH 變量 # 所有的 Android1.mk 的第一行配置都是該語(yǔ)句LOCAL_PATH := $(call my-dir)# II . 預(yù)編譯第三方動(dòng)態(tài)庫(kù)# 1 . 清除變量 ( add 模塊配置開(kāi)始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會(huì)清除 LOCAL_PATH 變量 # ③ 模塊開(kāi)始 : include $(CLEAR_VARS) # ④ 模塊結(jié)尾 : include $(XXX_STATIC_LIBRARY) / include $(XXX_SHARED_LIBRARY) include $(CLEAR_VARS)# 2 . 配置動(dòng)態(tài)庫(kù)名稱 # ① 自動(dòng)生成函數(shù)庫(kù)名稱前提 : 沒(méi)有 LOCAL_MODULE_FILENAME 配置 , 就會(huì)自動(dòng)生成函數(shù)庫(kù)名稱 # ② 動(dòng)態(tài)庫(kù)命名規(guī)則 : 在 LOCAL_MODULE 名稱基礎(chǔ)上 , 添加 lib 前綴 和 .so 后綴 # ③ 生成動(dòng)態(tài)庫(kù)名稱 : libadd.so LOCAL_MODULE := add# 3 . 預(yù)編譯的動(dòng)態(tài)庫(kù)路徑 LOCAL_SRC_FILES := libadd.so# 4 . 設(shè)置預(yù)編譯動(dòng)態(tài)庫(kù) ( add 模塊配置結(jié)束 ) include $(PREBUILT_SHARED_LIBRARY)# III . 打印變量值# 打印 LOCAL_PATH 值 # Build 打印內(nèi)容 : LOCAL_PATH : Y:/002_WorkSpace/001_AS/005_NDK_Compile/app/src/main/cpp # 編譯 APK 時(shí)會(huì)在 Build 中打印 $(info LOCAL_PATH : $(LOCAL_PATH))# IV . 配置動(dòng)態(tài)庫(kù)模塊# 1 . 清除變量 ( native-lib 模塊配置開(kāi)始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會(huì)清除 LOCAL_PATH 變量 include $(CLEAR_VARS)# 2 . 配置動(dòng)態(tài)庫(kù)名稱 # ① 自動(dòng)生成函數(shù)庫(kù)名稱前提 : 沒(méi)有 LOCAL_MODULE_FILENAME 配置 , 就會(huì)自動(dòng)生成函數(shù)庫(kù)名稱 # ② 動(dòng)態(tài)庫(kù)命名規(guī)則 : 在 LOCAL_MODULE 名稱基礎(chǔ)上 , 添加 lib 前綴 和 .so 后綴 # ③ 生成動(dòng)態(tài)庫(kù)名稱 : libnative-lib.so LOCAL_MODULE := native-lib# 3 . 編譯的源文件 LOCAL_SRC_FILES := native-lib.c# 4 . 設(shè)置靜態(tài)依賴庫(kù) # ① 依賴庫(kù) : 編譯 native-lib 模塊 , 需要鏈接 add 靜態(tài)庫(kù) # ② add 靜態(tài)庫(kù) : add 模塊是一個(gè)預(yù)編譯庫(kù) , 預(yù)編譯內(nèi)容是引入的第三方動(dòng)態(tài)庫(kù) LOCAL_SHARED_LIBRARIES := add# 5 . 鏈接日志庫(kù) LOCAL_LDLIBS := -llog# 6 . 設(shè)置預(yù)編譯動(dòng)態(tài)庫(kù) ( native-lib 模塊配置結(jié)束 ) include $(BUILD_SHARED_LIBRARY)# V . 配置動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)區(qū)別# 1 . 預(yù)編譯時(shí)的路徑不一致 : # ① 動(dòng)態(tài)庫(kù)路徑 : libadd.so # ② 靜態(tài)庫(kù)路徑 : libadd.a# 2 . 預(yù)編譯時(shí)結(jié)束配置不一致 : # ① 動(dòng)態(tài)庫(kù)配置 : include $(PREBUILT_SHARED_LIBRARY) # ② 靜態(tài)庫(kù)配置 : include $(PREBUILT_STATIC_LIBRARY)# 3 . 鏈接依賴庫(kù)時(shí)配置不一致 : # ① 動(dòng)態(tài)庫(kù)依賴配置 : LOCAL_SHARED_LIBRARIES # ② 靜態(tài)庫(kù)依賴配置 : LOCAL_STATIC_LIBRARIES
3 . Java 代碼示例
package kim.hsl.mk;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.widget.TextView;public class MainActivity extends AppCompatActivity {static {// 1 . 加載動(dòng)態(tài)庫(kù)的情況 : ( 必須不能注釋下面的代碼 )// ① 6.0 以下的版本 : 需要手動(dòng)加載依賴庫(kù) libadd.so// ② 6.0 以上的版本 : 無(wú)法使用 Android.mk 構(gòu)建腳本加載第三方動(dòng)態(tài)庫(kù)// 此情況下, 無(wú)論是否手動(dòng)加載 libadd.so 都會(huì)報(bào)錯(cuò)//// 2 . 加載靜態(tài)庫(kù)的情況 : ( 必須注釋掉下面的這行代碼 )System.loadLibrary("add");System.loadLibrary("native-lib");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView tv = findViewById(R.id.sample_text);tv.setText(stringFromJNI());}public native String stringFromJNI(); }
4 . C 代碼示例
#include <jni.h>#include <stdio.h> #include <stdlib.h>#include <android/log.h>//調(diào)用 libadd.so 動(dòng)態(tài)庫(kù)中的方法 extern int add(int a, int b);JNIEXPORT jstring JNICALL Java_kim_hsl_mk_MainActivity_stringFromJNI(JNIEnv *env,jobject obj) {//調(diào)用動(dòng)態(tài)庫(kù)中的函數(shù)int sum = add(1, 2);// Logcat 打印計(jì)算結(jié)果__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "Native Caculate : %d + %d = %d", 1, 2, sum);//將加法運(yùn)算轉(zhuǎn)為字符串char str[50] = "0";//字符串格式化sprintf(str, "Native Caculate : Static Library : %d + %d = %d", 1, 2, sum);return (*env)->NewStringUTF(env, str); }
5 . 運(yùn)行結(jié)果 ( Android 4.3 手機(jī) | 6.0 以上系統(tǒng)無(wú)法運(yùn)行 )
X . 博客資源
CSDN 博客地址 : 【Android NDK 開(kāi)發(fā)】Android.mk 配置動(dòng)態(tài)庫(kù) ( Android Studio 配置動(dòng)態(tài)庫(kù) | 動(dòng)態(tài)庫(kù)加載版本限制 | 本章僅做參考推薦使用 CMake 配置動(dòng)態(tài)庫(kù) )
博客資源下載地址 : https://download.csdn.net/download/han1202012/12157107
示例代碼 GitHub 地址 : https://github.com/han1202012/006_NDK_Android_mk
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Android NDK 开发】Ubun
- 下一篇: 【Android NDK 开发】Andr