Android之JNI① AS3.0以下DNK下載配置和第一個JNI程式
一、JNI介紹
JNI(Java Native Interface):一個協議,這個協議用來溝通java程式碼和外部的原生代碼(c/c++), 外部的c/c++程式碼也可以呼叫java程式碼。
1.1 C語言的優勢:
①效率上 C/C++是本地語言,比java更高效;
②程式碼移植,如果之前用C語言開發過模組,可以複用已經存在的c程式碼;
③java反編譯比C語言容易,一般加密演算法都是用C語言編寫,不容易被反編譯;
1.2 Java基本資料型別與C語言基本資料型別的對應:
Java型別 |
JNI型別 |
C/C++型別 |
大小 |
Boolean |
jboolean |
unsigned char |
無符號8位 |
Byte |
jbyte |
(signed) char |
有符號8位 |
Char |
jchar |
unsigned short |
無符號16位 |
Short |
jshort |
short |
有符號16位 |
Integer |
jint/jsize |
int / (一說為long) |
有符號32位 |
Long |
jlong |
long long/(一說_int64) |
有符號64位 |
Float |
jfloat |
float |
32位浮點值 |
Double |
jdouble |
double |
64位雙精度浮點值 |
1.3 引用型別對應
1.4堆記憶體和棧記憶體的概念
棧記憶體:系統自動分配和釋放,儲存全域性、靜態、區域性變數,在棧上分配記憶體叫靜態分配,大小一般是固定的
堆記憶體:程式設計師手動分配(malloc/new)和釋放(free/java不用手動釋放,由GC回收),在堆上分配記憶體叫動態分配,一般硬體記憶體有多大堆記憶體就有多大。
二、NDK
JNI的使用一定要先下載NDK,NDK是什麼:
- NDK是一系列工具的集合
- NDK提供了一份穩定、功能有限的API標頭檔案宣告
- NDK的釋出,使“Java+C”的開發方式終於轉正,成為官方支援的開發方式
- NDK將使Android平臺支援C開發的開端
2.1 兩種下載方式(第一種不耽誤AS的使用,第二種傻瓜式操作):
- 這是Google官方下載 點選下載NDK;
-
通過SDK Manger下載
點選SDK Manger -> SDK Tools -> NDK -> 點選Apply,等待,NDK下載完成
2.2 NDK的目錄結構:
docs: 幫助文件
build/tools:linux的批處理檔案
platforms:編譯c程式碼需要使用的標頭檔案和類庫
prebuilt:預編譯使用的二進位制可執行檔案
sample:jni的使用例子
source:ndk的原始碼
toolchains:工具鏈
ndk-build.cmd:編譯打包c程式碼的一個指令,需要配置系統環境變數
三、NDK配置(AS 3.0版本以下可用,3.0之後需要Android.mk+ndk-build配置編譯)
- 我們先建立一個專案,裡面只有一個MainActivity
- 右鍵專案 -> Open Module -> Android NDK Location -> OK -> 等待編譯
我們發現根目錄local.properties裡面多了NDK路徑如下圖:
接著我們在根目錄gradle.properties下面加上如下圖:android.useDeprecatedNdk=true(AS 3.0以上不支援)
繼續我們在module下面的build.gradle下面加上ndk節點如下圖:
ndk {
moduleName "JNISample"
}
四、編寫JNI介面
- 我們建立一個
JNIUtil
的類,編寫一個native
方法如下圖:
我們Build -> Make Project一下,我們會發現在/JniTestSample/app/build/intermediates/
下面多了一個classes
資料夾.我們可以開啟AS下面的Terminal
進入到classes
下面的debug
資料夾下
如下圖:
前面有重點有彎道,請注意
我們在Terminal
執行一下javah com.xiaoyuan.jnitestsample.JNIUtil
javah是後面是我的包名
你們一替換成自己的包名,執行完這句話以後會有個.h檔案生成出來如下圖所示:
我們基本已經完成一半了,但是我們發現很多小夥伴執行javah的時候會出現不少內部或者外部命令這樣的問題,這樣的問題大多數都是由於java環境變數沒有配好,如何配置環境變數,需要小夥伴自己百度一下了。
- 生成.h檔案不夠,這只是聲明瞭這個方法,我們還需要實現它,我在main檔案下新建一個
jni
資料夾如下圖:
新建以後,我們把剛才生成的.h檔案移動到你新建的jni資料夾下,緊接著我們建立一個c++類來實現.h裡面宣告的方法.
我們把.h類純複製一份,把字尾名改成.cpp。裡面實現它的方法,我們在方法裡面返回一句話;
如下圖:
上面include
就是咱們的導包,我們看他的方法名是有規律的就是java+包名+類名+方法名
。
接著我們在JNIUtil
裡面加上
static
{
System.loadLibrary("JNITestSample");//名字注意,需要跟你的build.gradle ndk節點 下面的名字一樣
}
讓系統載入我們編譯成的so。
最後我們來使用一下,看是否可以編譯so. 我們需要在MainActivity來使用一下如下圖:
我們執行一下:OK 我們已經順利的編譯出so如下圖:
並且我們的手機端已經顯示出了我們的“HelloWorld!”。
參考連結:
1. https://www.jianshu.com/p/81a97a43c176