在老早之前就想要去接觸瞭解這一塊的知識了,奈何在工做中一直都沒有機會去接觸,就遲遲沒有去學習這一塊的知識。到如今終於開始去學習了,簡單的搜索了一下,都沒有太明確的博客去學習,都是很零碎的,並且在最新的版本中也有問題,到最後只能去看官方的文檔,固然這才正確的選擇,其實一開始就該去看的。廢話很少說,這一個系列由於我纔開始學習,不知道會有多長,可是會將經常使用的東西所有總結學習完。java
首先來學習一下官方的配置。android
這一條沒啥說的,就是下載一些工具方便開發,固然是在Android Studio中。c++
對於ndk的開發,須要下載:bash
這三個均可以直接在SDK Manager中去下載(固然也能夠手動下載配置好)。目前我使用的版本對應分別是:ide
NDK : 17.1.4828580
cmake : 3.6.4111459
LLDB : 3.1.4508709
複製代碼
這一點分爲兩種狀況:函數
第一種狀況沒啥說的,就是在新建項目時,選中第一個界面的include C++ support
這個選擇框,以後一直默認next(最後finish)便可。工具
重點是第二種狀況,由於大多數在在項目一開始時可能沒有想着要使用ndk開發功能,後來須要了,那麼就去配置便可。學習
在已有項目的main目錄下建立cpp文件夾gradle
在cpp文件夾下建立一個c文件,右鍵->new->c/c++ Source File,例如取名叫作Hello,後綴名爲.c,不建立.h文件,點擊ok。ui
注:內部暫時能夠不用寫代碼。
在當前module中建立一個CMakeLists.txt文件,右鍵->new->File,取名叫作CMakeLists.txt
,點擊ok。加上如下代碼:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Specifies the name of the library.
Hello
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/Hello.c )
複製代碼
add_library方法:
選擇Android視圖,在須要構建的module下,右鍵->Link C++ Project with Gradle->選擇CMakeLists.txt的路徑,就是上文中建立的CMakeLists.txt,點擊ok。
構建完成,能夠看到在當前module下的build.gradle文件中多瞭如下這段話:
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
複製代碼
這時候再在當前的build.gradle中,android模塊,defaultConfig下,添加如下代碼:
ndk{
moduleName 'Hello'
}
複製代碼
這裏的moduleName就是要與CMakeLists.txt中定義的libraryName一致,這裏加入叫Hello吧。
到此基本配置就算是完成了。下面就開始寫代碼,先從java調用c開始。
到這一步,終於回到熟悉的Java代碼,咱們在對應的包名中建立一個類,例如取名叫作Hello,加入一個簡單的本地方法,只比普通抽象方法多了一個native關鍵字,以下:
public native String stringFromC();
複製代碼
這時候這個方法是找不到的,還須要在以前的Hello.c文件中寫上對應的方法,以下:
#include<jni.h>
jstring Java_net_arvin_androidstudy_jni_Hello_stringFromC(JNIEnv *env, jobject instance) {
return (*env)->NewStringUTF(env, "I am from c!");
}
複製代碼
代碼不長,以此來解釋,首先必需要引入的是jni.h
,下邊的JNIEnv和jstring,jobject等都是在這裏邊去定義的。
函數的申明部分,jstring
表示在java中定義的String,這個位置也就是返回值,而後Java_net_arvin_androidstudy_jni_Hello_stringFromC
這一部分看起來很長其實就是三個部分:Java_類的徹底限定名_方法名,只是徹底限定名中的點改成了下劃線,後邊的兩個參數env和instance,env是一個環境,用它能夠操做Java類,建立字符串之類的;instance就是當前調用這個代碼的類的實例,這裏就是Hello類的實例。
最後就是函數的實現內容,這裏是返回一個字符串而後,看一看env這個變量的類型,JNIEnv的定義能夠看到是一個typedef const struct JNINativeInterface* JNIEnv;
。自己就是指針,而後在方法中的env又是指針,至關於二級指針,因此調用的時候使用的就是(*env)->函數。
回到Hello類中,在類中加一段靜態初始化的代碼:
static {
System.loadLibrary("Hello");
}
複製代碼
其中Hello是上文中在build.gradle中ndk下配置的moduleName。
到這裏就能夠在其餘地方建立Hello類的實例,而後調用stringFromC的方法了。
例如:
Hello jni = new Hello();
System.out.println(jni.stringFromC());
複製代碼
就會在run tab下看到I am from c!
這樣一句話的輸出。
至此Android JNI開發系列之配置就告一段落了。固然後邊確定還有進一步的配置學習,例如須要引入多個c文件,須要引用其餘c++庫等,確定也是須要配置的,那些都會在以後的文章中講到。
借鑑官方教程