日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

發布時間:2025/6/17 Android 31 豆豆

文章目錄

        • I . Android Studio 中使用 Android.mk 配置動態庫 總結
        • II . 第三方動態庫來源
        • III . 配置 Android.mk 構建腳本路徑
        • IV . 預編譯 第三方 動態庫 ( Android.mk )
        • V . 鏈接動態庫 ( 設置動態庫依賴 )
        • VI . Java 代碼定義 native 方法并加載動態庫
        • VII . C 代碼調用動態庫函數
        • VIII . 動態庫加載版本限制 ( 6.0 以上 不能使用 Android.mk 配置動態庫 )
        • IX . 完整代碼示例
          • 1 . build.gradle 配置示例
          • 2 . Android.mk 配置示例
          • 3 . Java 代碼示例
          • 4 . C 代碼示例
          • 5 . 運行結果 ( Android 4.3 手機 | 6.0 以上系統無法運行 )
        • X . 博客資源



I . Android Studio 中使用 Android.mk 配置動態庫 總結



Android Studio 中使用 Android.mk 配置第三方 動態庫 :


① Android.mk 腳本路徑設置 : 在 Module 級別的 build.gradle 腳本中配置 Android.mk 構建腳本的路徑 ;

externalNativeBuild {ndkBuild{path "src/main/ndkBuild_Shared/Android.mk"}}

② 預編譯第三方動態庫 : 在 Android.mk 中預編譯動態庫 , 注意動態庫與靜態庫使用的配置不同 , 這里以動態庫舉例 :

include $(CLEAR_VARS) LOCAL_MODULE := add LOCAL_SRC_FILES := libadd.so include $(PREBUILT_SHARED_LIBRARY)

③ 鏈接動態庫 : 在 Android.mk 中預鏈接動態庫或靜態庫 , 注意動態庫與靜態庫使用的配置不同 , 這里以動態庫舉例 :

LOCAL_SHARED_LIBRARIES := add

④ Java 代碼實現 : 聲明 native 方法 , 加載編譯的動態庫 ;


⑤ C 代碼實現 : 聲明函數庫中的函數 , 調用動態庫中的函數 ;



II . 第三方動態庫來源



1 . 第三方動態庫源碼 : add.c ;

#include <stdio.h>int add(int a, int b){return a + b; }

2 . Ubuntu 交叉編譯過程 : 參考 【Android NDK 開發】Ubuntu 函數庫交叉編譯 ( Android 動態庫交叉編譯 | Android 靜態庫交叉編譯 ) , 最終編譯出 libadd.so 動態庫 , 和 libadd.a 靜態庫 ;



III . 配置 Android.mk 構建腳本路徑



1 . 源碼 編譯 / 打包 配置 原理 : 【Android NDK 開發】Android Studio 的 NDK 配置 ( 源碼編譯配置 | 構建腳本配置 | 打包配置 | CMake 配置 | ndkBuild 配置 ) : I . 源碼編譯配置


2 . 構建腳本路徑配置 原理 : 【Android NDK 開發】Android Studio 的 NDK 配置 ( 源碼編譯配置 | 構建腳本配置 | 打包配置 | CMake 配置 | ndkBuild 配置 ) : II . 構建腳本配置


3 . 這里直接設置 Android.mk 構建腳本路徑 : 省略無關配置 , 只保留 NDK 相關配置 ;

apply plugin: 'com.android.application'android {...defaultConfig {...// 配置 AS 工程中的 C/C++ 源文件的編譯// defaultConfig 內部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構建腳本的路徑externalNativeBuild {/*cmake {cppFlags ""//配置編譯 C/C++ 源文件為哪幾個 CPU 指令集的函數庫 (arm , x86 等)abiFilters "armeabi-v7a"}*/ndkBuild{abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}//配置 APK 打包 哪些動態庫// 示例 : 如在工程中集成了第三方庫 , 其提供了 arm, x86, mips 等指令集的動態庫// 那么為了控制打包后的應用大小, 可以選擇性打包一些庫 , 此處就是進行該配置ndk{// 打包生成的 APK 文件指揮包含 ARM 指令集的動態庫abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}// 配置 NDK 的編譯腳本路徑// 編譯腳本有兩種 ① CMakeList.txt ② Android1.mk// defaultConfig 內部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構建腳本的路徑externalNativeBuild {// 配置 CMake 構建腳本 CMakeLists.txt 腳本路徑/*cmake {path "src/main/cpp/CMakeLists.txt"version "3.10.2"}*/// 配置 Android1.mk 構建腳本路徑ndkBuild{path "src/main/ndkBuild_Shared/Android.mk"//path "src/main/ndkBuild_Static/Android.mk"}}... } ...

IV . 預編譯 第三方 動態庫 ( Android.mk )



1 . 清除變量 : ( add 模塊配置開始 )


① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 ;

② 例外情況 : 有一個例外 , 就是不會清除 LOCAL_PATH 變量 ;

③ 模塊開始標識 : include $(CLEAR_VARS) , 一般作為一個模塊配置的起始標志 ;

④ 模塊結尾 : include $(XXX_STATIC_LIBRARY) / include $(XXX_SHARED_LIBRARY) 一般作為模塊配置結束標志 ;

include $(CLEAR_VARS)

2 . 配置動態庫名稱 :


① 自動生成函數庫名稱前提 : 沒有 LOCAL_MODULE_FILENAME 配置 , 就會自動生成函數庫名稱 ;

② 動態庫命名規則 : 在 LOCAL_MODULE 名稱基礎上 , 添加 lib 前綴 ( 如果前面有 lib 前綴不再添加 ) 和 .so 后綴 ;

③ 生成動態庫名稱 : libadd.so ;

LOCAL_MODULE := add

3 . 設置預編譯的動態庫路徑 :

LOCAL_SRC_FILES := libadd.so

4 . 設置預編譯動態庫 : ( add 模塊配置結束 )

include $(PREBUILT_SHARED_LIBRARY)

5 . 完整的第三方動態庫預編譯模塊配置 :

# II . 預編譯第三方動態庫# 1 . 清除變量 ( add 模塊配置開始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會清除 LOCAL_PATH 變量 # ③ 模塊開始 : include $(CLEAR_VARS) # ④ 模塊結尾 : include $(XXX_STATIC_LIBRARY) / include $(XXX_SHARED_LIBRARY) include $(CLEAR_VARS)# 2 . 配置動態庫名稱 # ① 自動生成函數庫名稱前提 : 沒有 LOCAL_MODULE_FILENAME 配置 , 就會自動生成函數庫名稱 # ② 動態庫命名規則 : 在 LOCAL_MODULE 名稱基礎上 , 添加 lib 前綴和 .so 后綴 # ③ 生成動態庫名稱 : libadd.so LOCAL_MODULE := add# 3 . 預編譯的動態庫路徑 LOCAL_SRC_FILES := libadd.so# 4 . 設置預編譯動態庫 ( add 模塊配置結束 ) include $(PREBUILT_SHARED_LIBRARY)

V . 鏈接動態庫 ( 設置動態庫依賴 )



設置動態依賴庫 :


① 依賴庫 : 編譯 native-lib 模塊 , 需要鏈接 add 靜態庫 ;

② add 動態庫 : add 模塊是一個預編譯庫 , 預編譯內容是引入的第三方動態庫 ;

LOCAL_SHARED_LIBRARIES := add

# IV . 配置動態庫模塊# 1 . 清除變量 ( native-lib 模塊配置開始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會清除 LOCAL_PATH 變量 include $(CLEAR_VARS)# 2 . 配置動態庫名稱 # ① 自動生成函數庫名稱前提 : 沒有 LOCAL_MODULE_FILENAME 配置 , 就會自動生成函數庫名稱 # ② 動態庫命名規則 : 在 LOCAL_MODULE 名稱基礎上 , 添加 lib 前綴 和 .so 后綴 # ③ 生成動態庫名稱 : libnative-lib.so LOCAL_MODULE := native-lib# 3 . 編譯的源文件 LOCAL_SRC_FILES := native-lib.c# 4 . 設置動態依賴庫 # ① 依賴庫 : 編譯 native-lib 模塊 , 需要鏈接 add 動態庫 # ② add 動態庫 : add 模塊是一個預編譯庫 , 預編譯內容是引入的第三方動態庫 LOCAL_SHARED_LIBRARIES := add# 5 . 鏈接日志庫 LOCAL_LDLIBS := -llog# 6 . 設置預編譯動態庫 ( native-lib 模塊配置結束 ) include $(BUILD_SHARED_LIBRARY)

VI . Java 代碼定義 native 方法并加載動態庫



1 . 聲明 并使用 native 方法 :

public native String stringFromJNI();

2 . 加載動態庫 : 這里要加載兩個動態庫 ;

System.loadLibrary("add");System.loadLibrary("native-lib");



VII . C 代碼調用動態庫函數



1 . 聲明動態庫外部方法 :

//聲明 libadd.so 動態庫中的方法 extern int add(int a, int b);

2 . 調用動態庫的方法 :

//調用動態庫中的函數 int sum = add(1, 2);



VIII . 動態庫加載版本限制 ( 6.0 以上 不能使用 Android.mk 配置動態庫 )



1 . 問題描述 :

6.0 版本開始 , 使用 Android.mk 構建腳本預編譯第三方的動態庫 , 如果程序中使用 System.loadLibrary 加載該預編譯庫 , 就會報錯 ;

6.0 以下的手機版本 ( 不包括 6.0 版本 ) , System.loadLibrary 需要手動加載依賴的動態庫 ;

6.0 及以上的手機版本 , System.loadLibrary 會自動加載依賴的動態庫 , 此時不能加載依賴的動態庫 , 否則會出錯 ;


2 . 報錯信息 : 6.0 以上的手機 不能使用 Android.mk 加載動態庫 , 一旦加載崩潰 ; 報以下錯誤 ;

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 以上的手機 , 只能使用 CMake 配置動態庫 , 或者使用靜態庫 ;


4 . CMake 配置方案參考 : 【Android NDK 開發】NDK 交叉編譯 ( Ubuntu 中交叉編譯動態庫 | Android Studio 中配置使用第三方動態庫 )



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 內部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構建腳本的路徑externalNativeBuild {/*cmake {cppFlags ""//配置編譯 C/C++ 源文件為哪幾個 CPU 指令集的函數庫 (arm , x86 等)abiFilters "armeabi-v7a"}*/ndkBuild{abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}//配置 APK 打包 哪些動態庫// 示例 : 如在工程中集成了第三方庫 , 其提供了 arm, x86, mips 等指令集的動態庫// 那么為了控制打包后的應用大小, 可以選擇性打包一些庫 , 此處就是進行該配置ndk{// 打包生成的 APK 文件指揮包含 ARM 指令集的動態庫abiFilters "armeabi-v7a" /*, "arm64-v8a", "x86", "x86_64"*/}}// 配置 NDK 的編譯腳本路徑// 編譯腳本有兩種 ① CMakeList.txt ② Android1.mk// defaultConfig 內部的 externalNativeBuild 配置的是配置 AS 工程的 C/C++ 源文件編譯參數// defaultConfig 外部的 externalNativeBuild 配置的是 CMakeList.txt 或 Android1.mk 構建腳本的路徑externalNativeBuild {// 配置 CMake 構建腳本 CMakeLists.txt 腳本路徑/*cmake {path "src/main/cpp/CMakeLists.txt"version "3.10.2"}*/// 配置 Android1.mk 構建腳本路徑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 . 保存構建腳本的路徑 , 并賦值給 LOCAL_PATH 變量# ① 內置函數 : my-dir 是 NDK 內置的函數 , 獲取當前的目錄路徑 # 在該案例中就是 Android.mk 文件所在的目錄的絕對路徑 , 工程根目錄/app/src/main/cpp # 將該目錄賦值給 LOCAL_PATH 變量 # 所有的 Android1.mk 的第一行配置都是該語句LOCAL_PATH := $(call my-dir)# II . 預編譯第三方動態庫# 1 . 清除變量 ( add 模塊配置開始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會清除 LOCAL_PATH 變量 # ③ 模塊開始 : include $(CLEAR_VARS) # ④ 模塊結尾 : include $(XXX_STATIC_LIBRARY) / include $(XXX_SHARED_LIBRARY) include $(CLEAR_VARS)# 2 . 配置動態庫名稱 # ① 自動生成函數庫名稱前提 : 沒有 LOCAL_MODULE_FILENAME 配置 , 就會自動生成函數庫名稱 # ② 動態庫命名規則 : 在 LOCAL_MODULE 名稱基礎上 , 添加 lib 前綴 和 .so 后綴 # ③ 生成動態庫名稱 : libadd.so LOCAL_MODULE := add# 3 . 預編譯的動態庫路徑 LOCAL_SRC_FILES := libadd.so# 4 . 設置預編譯動態庫 ( add 模塊配置結束 ) include $(PREBUILT_SHARED_LIBRARY)# III . 打印變量值# 打印 LOCAL_PATH 值 # Build 打印內容 : LOCAL_PATH : Y:/002_WorkSpace/001_AS/005_NDK_Compile/app/src/main/cpp # 編譯 APK 時會在 Build 中打印 $(info LOCAL_PATH : $(LOCAL_PATH))# IV . 配置動態庫模塊# 1 . 清除變量 ( native-lib 模塊配置開始 ) # ① 作用 : 配置新的模塊之前都要先清除 LOCAL_XXX 變量 # ② 例外情況 : 但是不會清除 LOCAL_PATH 變量 include $(CLEAR_VARS)# 2 . 配置動態庫名稱 # ① 自動生成函數庫名稱前提 : 沒有 LOCAL_MODULE_FILENAME 配置 , 就會自動生成函數庫名稱 # ② 動態庫命名規則 : 在 LOCAL_MODULE 名稱基礎上 , 添加 lib 前綴 和 .so 后綴 # ③ 生成動態庫名稱 : libnative-lib.so LOCAL_MODULE := native-lib# 3 . 編譯的源文件 LOCAL_SRC_FILES := native-lib.c# 4 . 設置靜態依賴庫 # ① 依賴庫 : 編譯 native-lib 模塊 , 需要鏈接 add 靜態庫 # ② add 靜態庫 : add 模塊是一個預編譯庫 , 預編譯內容是引入的第三方動態庫 LOCAL_SHARED_LIBRARIES := add# 5 . 鏈接日志庫 LOCAL_LDLIBS := -llog# 6 . 設置預編譯動態庫 ( native-lib 模塊配置結束 ) include $(BUILD_SHARED_LIBRARY)# V . 配置動態庫與靜態庫區別# 1 . 預編譯時的路徑不一致 : # ① 動態庫路徑 : libadd.so # ② 靜態庫路徑 : libadd.a# 2 . 預編譯時結束配置不一致 : # ① 動態庫配置 : include $(PREBUILT_SHARED_LIBRARY) # ② 靜態庫配置 : include $(PREBUILT_STATIC_LIBRARY)# 3 . 鏈接依賴庫時配置不一致 : # ① 動態庫依賴配置 : LOCAL_SHARED_LIBRARIES # ② 靜態庫依賴配置 : 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 . 加載動態庫的情況 : ( 必須不能注釋下面的代碼 )// ① 6.0 以下的版本 : 需要手動加載依賴庫 libadd.so// ② 6.0 以上的版本 : 無法使用 Android.mk 構建腳本加載第三方動態庫// 此情況下, 無論是否手動加載 libadd.so 都會報錯//// 2 . 加載靜態庫的情況 : ( 必須注釋掉下面的這行代碼 )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>//調用 libadd.so 動態庫中的方法 extern int add(int a, int b);JNIEXPORT jstring JNICALL Java_kim_hsl_mk_MainActivity_stringFromJNI(JNIEnv *env,jobject obj) {//調用動態庫中的函數int sum = add(1, 2);// Logcat 打印計算結果__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "Native Caculate : %d + %d = %d", 1, 2, sum);//將加法運算轉為字符串char str[50] = "0";//字符串格式化sprintf(str, "Native Caculate : Static Library : %d + %d = %d", 1, 2, sum);return (*env)->NewStringUTF(env, str); }

5 . 運行結果 ( Android 4.3 手機 | 6.0 以上系統無法運行 )




X . 博客資源



CSDN 博客地址 : 【Android NDK 開發】Android.mk 配置動態庫 ( Android Studio 配置動態庫 | 動態庫加載版本限制 | 本章僅做參考推薦使用 CMake 配置動態庫 )

博客資源下載地址 : https://download.csdn.net/download/han1202012/12157107

示例代碼 GitHub 地址 : https://github.com/han1202012/006_NDK_Android_mk

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本免费在线 | 亚洲人成无码www久久久 | www久久久久久久 | 永久免费未满蜜桃 | 国产精品揄拍100视频 | 夜夜骑夜夜操 | 午夜精品美女久久久久av福利 | 成人免费观看视频大全 | 福利一区二区在线观看 | 日韩一页| 女~淫辱の触手3d动漫 | 亚洲黄色成人网 | 福利姬在线播放 | 大尺度av | 女人18毛片一区二区三区 | 日韩视频免费在线 | 久久久久久久综合 | 狼人综合视频 | 成年人精品 | 狼人狠狠干 | 日韩人妻无码精品久久免费 | 九九热在线视频 | 人妻在客厅被c的呻吟 | 丰满人妻一区二区三区免费视频 | 亚洲国产精品无码久久 | 国产精品一级二级三级 | 波多野结衣在线影院 | 欧美30p | 中文写幕一区二区三区免费观成熟 | 成人午夜激情 | 欧州一区二区 | 精品亚洲在线 | 亚洲国产精品一区二区尤物区 | 婷婷91| 最近日韩中文字幕中文 | 天天综合色网 | 爱草在线 | 啪啪免费网站 | 夜夜干天天操 | 福利一区二区视频 | 欧美性一级 | 97超碰在线资源 | 香蕉国产精品 | 亚洲色图19p | 欧美精品在线播放 | 国产中文一区 | 日本一区二区三区在线观看 | 九九亚洲视频 | 天堂av.com| 亚洲精品久久久久avwww潮水 | 国产性猛交╳xxx乱大交一区 | 免费看一级一片 | 午夜国产视频 | 五月天婷婷基地 | 神马午夜我不卡 | 国产乱子伦一区二区 | 精品999久久久 | 国产一区二区h | 国产情侣一区二区三区 | 亚洲一区在线电影 | 欧美日本色 | 噜噜噜久久久 | 亚洲人成电影在线 | 成人在线你懂的 | 精品国产免费观看 | 水果派解说av | 加勒比精品在线 | 97人妻精品一区二区 | 综合图区亚洲 | 狠狠干在线观看 | 少妇人妻邻居 | 日韩精品观看 | 日本涩涩网站 | 国产老熟女伦老熟妇露脸 | 久久国产在线观看 | 91porny九色| 久久人人干 | 成人高清免费 | 91亚色在线观看 | 91视频这里只有精品 | 六月婷婷综合网 | 国产精品蜜 | 黄色激情小说视频 | 黄色不卡av| 国产午夜精品一区二区三区视频 | 无码人妻aⅴ一区二区三区有奶水 | 黄色av免费在线播放 | 亚洲精品大片 | 老妇高潮潮喷到猛进猛出 | 四虎啪啪 | 一级黄色片一级黄色片 | 91精品国产高清一区二区三蜜臀 | 欧美久操| 天天操天天插 | 天天操国产 | 免费欧美黄色 | 男男野外做爰全过程69 | 肮脏的交易在线观看 | 秋霞影院一区二区 |