目前有很多的招聘公司,在招聘android程序工程師的時候,在應聘要求中明確的提出了要熟悉NDK開發,或者是瞭解JNI開發,甚至是精通NDK和JNI開發,很多小夥伴對JNI都有所耳聞,特別是研究過java虛擬機的同學,但是這種對jni的瞭解,並沒有使他們擁有精通jni的勇氣,反而使他們感覺jni很難,反而不想去學,產生了畏難的心理,對於一些沒有接觸過jni的同學來說呢,剛開始是報着必勝的心態去學習JN的,但是因爲一直學習的是java,一看現在jni還要牽涉到C語言,頓時感覺jni無比的高深,在心理上就首先投降了JNI。
JNI真的很難嗎?
android工程師必須要學習JNI嗎?
應該怎麼學習JNI?
接下來,我通我對jni的學習來闡述一下我的觀點:
首先:說一句,jni不簡單,但是作爲android工程師,我們沒有必要精通jni;
什麼是JNI(Java Native Interface)?
其實JNI就是java接口語言(不是等於沒說嗎???),那什麼又是java接口語言呢?說白了,就是我們的java程序調用C程序的一個過度,一個翻譯,在此有很多人有一個誤解,就是一直以爲jni是android的技術,其實這種想法是錯誤的,jni是java中的技術,例如當我們用java在windows上開發程序,用jin調用系統的C代碼是很經常的,我們的運行在windows上的JVM也是依靠JNI和windows來進行溝通的。
什麼是NDK?
NDK是google爲方便Android開發者通過C/C++本地語言編寫應用的開發包,其中有很多工具,比如我們在windows環境上寫好C代碼,我們可以用其中的ndk-build把C代碼打包成.so文件(.so文件是運行在linux上的函數庫文件)。
解壓後的NDK文件目錄:
jni和ndk的具體概念我們已經瞭解了,接下來我們就來看看如何開發jni程序:
首先還有講解一下,C代碼在windows上和在linux上的一些不同
Windows:
C -> .O -> .exe .dll(wendow下的函數庫)
Linux:
C-> .O ->.elf .so(Linux下的函數庫) .a(linux下的靜態函數庫)
我們在android項目中,就是要把我們寫的c代碼打包成.so文件庫,供java調用
開發步驟:
一:在java代碼中創建一個native方法:
public native String helloWorldFromC();
二:在android工程這中創建一個jni文件夾
三:在jni文件夾中寫c代碼,c代碼中要有include<jni.h>
c代碼中的方法名,應該是Java_加上全類名(把全類名的“.”變爲“_”)加上java native的方法名
方法名也可以不用手寫,當定義好java的native方法後,在控制檯輸入 javah [類的全類名],此時可以得到c語言實現java代碼的頭文件,把頭文件導入jni文件夾中,並且在實現的c代碼中導入該頭文件,方法名從頭文件中複製即可;
四:把c代碼打包成函數庫:在控制檯進入到工程目錄,然後ndk-build;
注意:在ndk-build之前,jni文件夾中還需要有一個Android.mk文件;
Android.mk:告訴編譯器如何把C代碼打包成函數庫,此文件也在jni文件夾
五:在java代碼中引入函數庫
注意:引入函數庫的時候,不要看見xxxx.so,就把前面的名字引入,而是寫自己在android.mk文件中定義的要打包的函數庫的名字,此時應該是hello;
六:java中調用方法
在此打印一個Toast:
最後目錄結構爲:
以上就是比較簡單但是非常全面的在android中開發jni的步驟。
接下來我們來看一下怎麼在java調用c代碼的時候,向其傳遞參數:
在此只貼出代碼,其原理都是一樣的,只是一些規則和細節,需要查閱相關資料:
java本地代碼:
C代碼:
注意:當我們傳遞java字符串時,在jni中,我們應該把java字符串轉換爲C代碼中的字符數組,用如下方法即可:
Sdk開發常見錯誤:
1.java Native 不能是private的;
2.Jni文件夾命名錯誤;
3.方法名稱寫錯(因爲比較長,所以要注意)
4.直接工程異常,沒有日誌打印,一般是c代碼運行錯誤;
5.Android.mk文件中不要用中文的回車和空格
6.引用別人的函數庫(.so文件),需要自己的含有native方法的包名和函數庫的方法名中的包名一致;
通過以上的講解,我再來回到在文章開頭提問的幾個問題:
JNI難嗎?
JNI本身並不簡單,只是根據自己所處的領域,和自己的實際情況來決定學習的深度,當然如果對這方面比較有興趣,多學習一些東西總是好的。
android工程師有必要學習JNI嗎?
在android開發中,比如加密,計算等一些問題,我們爲了提高效率或者安全方面的考慮,JNI確實是一個很好的選擇,但是在android開發中一個項目中並不會大量的使用,所以,我們學習的時候,沒有必要去鑽牛角尖。
應該怎麼學習JNI?
看文檔,看NDK中的頭文件。