基本概念

開發 Android app 如果需要使用 native library,簡單地說其實不複雜,就是把 .so 檔放到 lib/<abi> 目錄,然後不管你是用 Eclipse ADT, Ant, 或是 Gradle 來產生 APK, 這些工具都會把這些 .so 包到 .apk 裡面,然後這些 .so 就可以在運作時期用 System.loadLibrary 或是 System.load 來載入。

接下來說明幾個常見的 .so 產生及載入方式:

使用 NDK

如果是自己開發自己使用,通常建議用 Android NDK,只要一個 ndk-build 命令就可以將 jni/ 目錄裡的 C/C++ code 編譯成 libs/<abi>/ 裡的 lib<name>.so

載入方式就是直接使用 System.loadLibrary

Third-party library

但如果角色換成是要提供 library 給 App 開發者使用,方法就比較多樣一點:

jni/ + src/

也就是直接給 JNI 及 Java code 由 App 開發自己整合。

Library Project

如果你要提供的 library 有自帶的 resource,這是目前唯一可以用的方式。把 .so 放在 library project 的 libs/<abi> 就可以讓 app project 使用了。據說 Google 以後會提供工具可以把 library project 輸出成單一檔案來使用,期待中。

一個 .jar + 數個 .so

如果不帶 resource 的話,給編譯好的 .jar.so 讓 App 開發者直接放到 libs/ 也是種簡單的方法。

一個 .jar 內嵌 .so

有些 library 提供者為了降低開發者的使用門檻,使用了把 .so 放在 .jar 檔的 assets/ 目錄中然後運作時再從 assets 中取出 .so 來載入的技巧,細節可以參考 Crittercism SDK 用的方式

獨立的 library APK

上述的所有方法都有個缺點(或者也是優點): app 都自帶 .so,不同 app 間無法共享占用空間多,也無法獨立更新。所以就有人想了把 .so 放在獨立的 APK 裡,只要能找到 .so 的絕對安裝路徑就能用 System.load 來載入使用。例如 OpenCV 就是使用這樣的技巧:

Android App Usage Model

  1. 由 library APK 提供一個 service。
  2. App 透過 service 獲取 lib 的絕對路徑。
  3. 但如果 service 不存在可以由 App 透過 Play store 來安裝。
  4. App 使用 System.load(libpath) 來載入 .so

但這樣相對地 library 要做的事情就蠻多的,細節可以參考 OpenCV 的做法

總結

上面的方法各有其適用的時機,該用那一種就是大家自己去思考及評估囉。