本文主要講解了在Windows環境下如何使用ndk-build構建工具來進行NDK開發,以及ndk-build構建工具在Android Stuido中的快捷工具配置。java
在上一篇文章《Android NDK開發(一) 使用CMake構建工具進行NDK開發》中,咱們學習瞭如何使用CMake構建工具來進行NDK開發,可是一些老項目仍是使用的ndk-build構建工具進行開發的,今天咱們就來學習一下如何使用ndk-build構建工具。android
在SDK Tools中安裝NDK開發環境(File > Settings > Appearance & Behavior > System Settings > Android SDK > SDK Tools):git
新建一個普通的Android項目,在main目錄下新建jni目錄,在此目錄下編寫原生代碼:github
在main目錄下新建jniLibs目錄,此目錄爲Android Stuido加載so文件的默認目錄,看下項目結構:bash
打開File > Settings > Tools > External Tools選項,點擊【+】按鈕添加生成jni頭文件以及ndk-build命令的快捷工具:markdown
生成頭文件app
Name:javah-jniide
工具名稱工具
Program:$JDKPath$/bin/javahoop
javah所在的路徑,$JDKPath$表明在環境變量中配置的JDK路徑。
Parameters:-jni -encoding UTF-8 -d $ModuleFileDir$\src\main\jni $FileClass$
命令參數:
-jni表明生成JNI樣式的標頭文件,文件名爲當前包名+類名($FileClass$)
-encoding表明編碼格式爲UTF-8
-d表明指定頭文件的輸出路徑爲jni目錄($ModuleFileDir$\src\main\jni )
Working directory:$ModuleFileDir$\src\main\java
工做目錄,$ModuleFileDir$爲當前module的路徑。
javah用法: javah [options] <classes> 其中, [options] 包括: -o <file> 輸出文件 (只能使用 -d 或 -o 之一) -d <dir> 輸出目錄 -v -verbose 啓用詳細輸出 -h --help -? 輸出此消息 -version 輸出版本信息 -jni 生成 JNI 樣式的標頭文件 (默認值) -force 始終寫入輸出文件 -classpath <path> 從中加載類的路徑 -cp <path> 從中加載類的路徑 -bootclasspath <path> 從中加載引導類的路徑 <classes> 是使用其全限定名稱指定的 (例如, java.lang.Object)。 複製代碼
NDK構建
ndk-build的配置和javah-jni相似,其中C:\Tools\NDK\android-ndk-r14b\ndk-build.cmd爲ndk-build構建工具的路徑,須要按照實際NDK安裝路徑進行修改。
如何調用
右擊項目選擇External Tools:
準備工做都作完了,下面進入正題,看下MainActivity:
public class MainActivity extends AppCompatActivity { // 加載native-lib,不加lib前綴 static { System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 將獲取的字符串顯示在TextView上 TextView tv = findViewById(R.id.sample_text); tv.setText(stringFromJNI()); } /** * native-lib中的原生方法 */ public native String stringFromJNI(); } 複製代碼
首先加載native-lib庫,而後調用其中的stringFromJNI方法,將其返回的字符串顯示在TextView上,此時尚未native-lib庫,別急,繼續往下看:
對着MainActivity的類名右擊鼠標,選擇External Tools > javah-jni,控制檯執行完命令後,會在jni目錄生成一個頭文件:
看下生成的頭文件:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_yl_ndkdemo_MainActivity */ #ifndef _Included_com_yl_ndkdemo_MainActivity #define _Included_com_yl_ndkdemo_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: com_yl_ndkdemo_MainActivity * Method: stringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_yl_ndkdemo_MainActivity_stringFromJNI (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif 複製代碼
能夠看到第一行註釋寫到:這是自動生成的,不要去修改它。好,不改就不改,Go on:
在jni目錄中新建cpp類native-lib.cpp:
#include "com_yl_ndkdemo_MainActivity.h" JNIEXPORT jstring JNICALL Java_com_yl_ndkdemo_MainActivity_stringFromJNI (JNIEnv *env, jobject) { return env->NewStringUTF("Hello from C++"); } 複製代碼
引用上文中生成的頭文件,返回一個字符串給Java層,方法名是經過 Java_包名_類名_方法名 的方式命名的。
接着在jni目錄下建立Android.mk和Application.mk配置文件,分別來看看:
Android.mk
# 當前路徑 LOCAL_PATH := $(call my-dir) # 清除LOCAL_XXX變量 include $(CLEAR_VARS) # 原生庫名稱 LOCAL_MODULE := native-lib # 原生代碼文件 LOCAL_SRC_FILES =: native-lib.cpp # 編譯動態庫 include $(BUILD_SHARED_LIBRARY) 複製代碼
在app的build.gradle文件中關聯Android.mk:
android { ... externalNativeBuild { ndkBuild { path 'src/main/jni/Android.mk' } } } 複製代碼
至關於執行了【Link C++ Project with Gradle】:
Application.mk
# 原生庫名稱 APP_MODULES := native-lib # 指定機器指令集 APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64 複製代碼
到這裏基本的開發流程就已經完成了,運行程序看下效果:
分析一下APK文件,能夠看到so文件已經打包進去了:
對着jni目錄右擊鼠標,選擇External Tools > ndk-build,會在main目錄下生成libs和obj目錄,編譯出的so文件就在libs目錄下:
將so文件拷貝到jniLibs目錄下就能夠正常使用了,也能夠在app的build.gradle文件中設置so文件的路徑。
注意:編譯出的so文件就至關於java中的jar包,上文中的jni就至關於library,二者不要重複使用。
在ndk-build的過程當中遇到了下面這行警告,可是沒有影響編譯so文件,沒有找到好的解決方法,有知道的同窗能夠留言告訴我,多謝!
Android NDK: WARNING: Unsupported source file extensions in jni/Android.mk for module native-lib 複製代碼
源碼已經上傳到GitHub上了,歡迎Fork,以爲還不錯就Start一下吧!