基本概念
開發 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 就是使用這樣的技巧:
- 由 library APK 提供一個 service。
- App 透過 service 獲取 lib 的絕對路徑。
- 但如果 service 不存在可以由 App 透過 Play store 來安裝。
- App 使用
System.load(libpath)
來載入.so
。
但這樣相對地 library 要做的事情就蠻多的,細節可以參考 OpenCV 的做法。
總結
上面的方法各有其適用的時機,該用那一種就是大家自己去思考及評估囉。