­

將 so|JNI|NDK 之間的關係說明白

  • 2019 年 10 月 27 日
  • 筆記

最近在了解公司歷史的發展,發現了公司產品中幾乎都要使用 so 文件,不禁好奇這個 so 到底是何方神聖。

so 文件

soshared object 的縮寫,見名思義就是共享的對象,機器可以直接運行的二進位程式碼。so 主要存在於 UnixLinux 系統中。【參考:Androidso文件是什麼,又是如何開發出來的呢? 】
它是 c/c++ 實現的功能函數集合,並對外提供標準的介面,外層可以通過這個介面調用c/c++的程式碼。在 Android 系統上普遍用於調用系統的硬體介面。

那麼,Android 系統為什麼要使用.so文件呢?

Android 系統應用基本都是基於 Java 語言開發,而Java語言是不能直接訪問Android系統底層的硬體介面。而Android系統中可以通過 JNI硬體訪問服務去訪問系統底層的硬體介面。比如:開啟藍牙、關閉藍牙等

這裡還有一個問題:為什麼 Java不能直接訪問Android系統底層的硬體呢?

  1. Java語言是跨平台的。【個人想法】:跨平台就會導致最後使用的平台是不確定的,因此要訪問的底層硬體介面也是不確定的。
  2. 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 程式碼

特別注意:

  • JNIJava 調用 Native 語言的一種特性
  • JNI 是屬於 Java 的,與 Android 無直接關係

【以上內容參考:Android JNI】

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的功能。