將 so|JNI|NDK 之間的關係說明白
- 2019 年 10 月 27 日
- 筆記
最近在了解公司歷史的發展,發現了公司產品中幾乎都要使用
so
文件,不禁好奇這個so
到底是何方神聖。
so 文件
so
是shared object
的縮寫,見名思義就是共享的對象,機器可以直接運行的二進位程式碼。so
主要存在於Unix
和Linux
系統中。【參考:Androidso文件是什麼,又是如何開發出來的呢? 】
它是c/c++
實現的功能函數集合,並對外提供標準的介面,外層可以通過這個介面調用c/c++
的程式碼。在Android
系統上普遍用於調用系統的硬體介面。
那麼,Android
系統為什麼要使用.so
文件呢?
Android
系統應用基本都是基於Java
語言開發,而Java
語言是不能直接訪問Android
系統底層的硬體介面。而Android
系統中可以通過JNI
和硬體訪問服務
去訪問系統底層的硬體介面。比如:開啟藍牙、關閉藍牙等
這裡還有一個問題:為什麼 Java
不能直接訪問Android
系統底層的硬體呢?
Java
語言是跨平台的。【個人想法】:跨平台就會導致最後使用的平台是不確定的,因此要訪問的底層硬體介面也是不確定的。Android
是基於Linux
系統,而有些Linux
系統調用是不支援Java
的,比如ioctl
,只能C/C++
才能調用。【參考:Android硬體訪問服務(一)
"使用JNI直接操作硬體"】
既然知道了Android
系統中可以通過 JNI
和 硬體訪問服務
去訪問系統底層的硬體介面。
那麼先來了解一下什麼是JNI
吧
JNI
定義:
Java Native Interface
,即Java
本地介面
作用: 使得Java 與 本地其他類型語言(如C、C++
)交互
即在Java
程式碼 里調用C、C++
等語言的程式碼 或C、C++
程式碼調用Java
程式碼
特別注意:
JNI
是Java
調用Native
語言的一種特性JNI
是屬於Java
的,與Android
無直接關係
JNI
程式碼經過編譯之後在Unix/Linux
系統上就會生成 .so
文件,通過調用Java
程式碼調用.so
中的介面方法即可實現硬體的訪問。
JNI
相關的內容還是比較複雜的,可以自行搜索了解,這裡只是簡單介紹。
可以參考這兩篇系列【JNI詳解—從不懂到理解 】,【Android JNI(一)——NDK與JNI基礎】
JNI
方式去訪問硬體有一個弊端,就是只能一個應用調用一個硬體介面,而多個應用去調用該硬體介面就會出現衝突,那麼硬體訪問服務
的方式就是解決JNI
的弊端。
硬體訪問服務
的定義如下:
訪問硬體資源的程式只能並且只有一個,我們稱之為
System Server
, 其它要訪問這個硬體資源的APP
必須要給Server
發請求,由Server
間接的操作硬體,從而實現資源的訪問。這個就稱之為硬體訪問服務。【參考:Android訪問硬體的方法】
更多硬體訪問服務的資料
:
【Android硬體訪問服務-Service】
【Android驅動(一)硬體訪問服務學習之(二)Android通過硬體訪問服務訪問硬體】
在 Android
系統下 JNI
可以通過NDK
快速實現。那麼NDK
又是什麼呢?
NDK
NDK
全稱:Native Develop Kit
,是Android
的一個工具開發包NDK
是屬於Android
的,與Java
並無直接關係.
使用教程【NDK 入門指南】
通過Android Studio
編譯之後就可以生成 .so
文件,之後就可以愉快的將 .so
文件集成到項目中了。
總結
我們首要目的就是要了解.so
文件的作用是用來訪問系統底層的硬體介面,而Android
應用基本都是Java
開發,而Java
不支援直接訪問硬體,但是Android
提供了兩種方式去訪問硬體介面:JNI
和硬體訪問服務
。JNI
的方式編譯後會產生.so
文件。同時Android
還給開發者提供了NDK
這個開發工具包,開發者可以使用NDK
快速實現 JNI
的功能。