安卓JAVA JNI NDK 基礎使用樣例 附實作的詳細步驟
- 開發環境
- 實作步驟
最近做安卓專案需要使用到JNI的知識呼叫C檔案,在網上搜尋了近兩天的資料踩了很坑,總結了一套在安卓中使用JNI的步驟,記錄在這里順便提供給像我一樣剛接觸的朋友們做一個參考,
JNI的用途就是實作在Java代碼中呼叫c/c++語言的方法,具體的原理之類的我就不說了百度說的很多,先介紹下環境
開發環境
Android Studio 4.2.2
SDK:API 30
SDK Build-Tools:30.0.3
NDK :21.4.7075529(下載于Android Studio )
專案:minSdk 24,targetSdk 30
環境基本不會影響最終結果,但還是列出來以防萬一,下面直接上步驟
實作步驟
-
在AS中的專案右鍵創建檔案夾jni,選擇下方自動彈出的src/main/jni(藍色檔案夾)
-
在java原始碼目錄下創建一個工具類用來保存native方法,如
package com.example.testaidl; public class JNIHelper { static { // 加載庫檔案 System.loadLibrary("JNIHelper"); } public static native String getName(); }這時AS會說找到不對應的本地方法的實作,先不管,接著往下走
-
到工具類檔案的所在目錄使用javac命令編譯出class檔案
-
在當前目錄新建一個檔案夾,把class檔案放進去,再在新建出來的檔案夾下運行javah -classpath 絕對路徑 packagename.classname
- packagename為包名,使用點號隔開
- 如
javah -classpath D:\WorkSpace\MyFirstApp\testaidl\src\main\java com.example.testaidl.JNIHelper注意包名前有一個空格
-
在新建的檔案夾中即會生成 .h頭檔案
-
(非必須)
將頭檔案中的#include <jni.h>改成#include "jni.h" -
到jdk目錄中找到jni.h和jni_md.h檔案,拷貝到專案jni目錄中,第五步自動生成的.h檔案及c/c++原始碼也一起拷貝到jni目錄中
需要使用對應系統版本的jdk(win對win,linux對linux),不同系統的jdk里面的jni.h和jni_md.h檔案不同,會導致編譯失敗
-
在jni目錄中撰寫兩個mk檔案(直接New File創建)
-
Android.mk
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) #指定生成的so庫檔案名稱 LOCAL_MODULE:= JNIHelper #指定對應的c原始碼,多個原始碼間用空格分隔 LOCAL_SRC_FILES:= JNIHelper.c LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) include $(BUILD_SHARED_LIBRARY) -
Application.mk
#需要與Android.mk檔案中的LOCAL_MODULE一致 APP_MODULES = JNIHelper APP_PLATFORM := android-24 APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 APP_STL := c++_shared ifeq ($(NDK_DEBUG), 1) APP_OPTIM = debug APP_CFLAGS = -g -O0 else APP_OPTIM = release APP_CFLAGS = -O3 endif
-
-
在專案AndroidManifest.xml中添加
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30"/> -
在module的build.gradle檔案中添加
defaultConfig{ #注意這個ndk節點是寫到AndroidManifest對應的defaultConfig節點中 ndk{ //設定so庫檔案名稱 moduleName "JNIHelper" // 宣告創建指定cpu架構的so庫 abiFilters "arm64-v8a", "armeabi-v7a", "x86" } } android{ #注意這個externalNativeBuild節點是寫到AndroidManifest對應的android節點中 externalNativeBuild{ ndkBuild{ path "src/main/jni/Android.mk" } } } -
在AndroidStudio中下載NDK,隨后重新build module,build通過后直接到專案jni目錄運行
ndk-build命令(需要提前為NDK配置環境變數或直接使用絕對路徑),成功后就會在專案src/main目錄下生成libs檔案夾,其中有對應不同架構的so庫檔案- 可能會遇到include的頭檔案不存在報錯的問題,這是因為新版本的ndk不再附帶platforms/android-xx(api版本)/arch-xx(架構)/usr/include檔案夾,頭檔案本應當根據不同的架構放置在不同架構檔案夾中的此處,
- 解決可以通過下載ndk12b(谷歌官網下載地址:https://developer.android.google.cn/ndk/downloads/older_releases?hl=de),解壓
/android-ndk-r12b/platforms/android-24/目錄下各個架構的include檔案夾進新版ndk,具體拷貝到新版ndk的哪個api檔案夾則取決于你專案的targetSdk的api版本 - 或將/android-ndk-r12b/platforms/android-24/arch-x86_64/usr/中的include檔案單獨拷貝出來,然后在Android.mk檔案中添加LOCAL_C_INCLUDES屬性指定include檔案夾位置,如LOCAL_C_INCLUDES := /home/local/Android/include,但此方法能否適配不同架構的系統還未能驗證,建議使用第一種解決方式
- 解決可以通過下載ndk12b(谷歌官網下載地址:https://developer.android.google.cn/ndk/downloads/older_releases?hl=de),解壓
- 可能會遇到include的頭檔案不存在報錯的問題,這是因為新版本的ndk不再附帶platforms/android-xx(api版本)/arch-xx(架構)/usr/include檔案夾,頭檔案本應當根據不同的架構放置在不同架構檔案夾中的此處,
-
在JNIHelper類中的本地方法已可使用
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/291224.html
標籤:其他
下一篇:【Android 事件分發】MotionEvent.ACTION_DOWN 按下事件分發流程( Activity | ViewGroup | View )
