發布使用 NDK 建構的中介軟體時會引發其他問題,但應用程式開發人員無需為此感到擔心。預建程式庫會為使用者提供一些實作選項。
選擇 API 級別和 NDK 版本
您的使用者使用的 minSdkVersion 版本不能比您低。如果使用者的應用程式需要在 API 21 上執行,您就無法針對 API 24 進行建構。您可以針對「低於」使用者的 API 級別建構程式庫,例如針對 API 16 建構程式庫,並保持與 API 21 使用者相容。
各 NDK 版本大多彼此相容,但版本間的變更偶爾會破壞相容性。如果您確定所有使用者都使用相同的 NDK 版本,則建議您也使用與使用者相同的版本,不然就是使用最新版本。
使用 STL
若您正在編寫 C++ 和使用 STL,並且要發布共用程式庫,那麼您在 libc++_shared
和 libc++_static
之間的選擇將會對使用者造成影響。如果您要發布共用程式庫,則必須使用 libc++_shared
,或確保程式庫不會公開 libc++ 的符號。最佳做法是使用版本指令碼明確宣告您的 ABI 介面 (這樣也有助於保持實作細節的私密性)。例如,一個簡單的算術程式庫可能包含下列版本指令碼:
LIBMYMATH {
global:
add;
sub;
mul;
div;
# C++ symbols in an extern block will be mangled automatically. See
# https://stackoverflow.com/a/21845178/632035 for more examples.
extern "C++" {
"pow(int, int)";
}
local:
*;
};
建議優先使用版本指令碼,因為這個版本最完善 控制符號的顯示設定這是所有共用者 或中介軟體庫,否則無法擷取實作詳細資料 也可以縮短載入時間
另一個較不可靠的做法是連結時使用 -Wl,--exclude-libs,libc++_static.a
-Wl,--exclude-libs,libc++abi.a
。這個方法不可靠
只會隱藏程式庫中明確命名的符號,
系統會針對未使用的程式庫回報診斷資料 (程式庫中的錯字)
名稱未發生錯誤,且使用者必須讓程式庫清單保持顯示
。這種做法也不會隱藏您自己的實作細節。
在 AAR 中發布原生資料庫
Android Gradle 外掛程式可匯入以 AAR 形式發布的原生依附元件。如果您的使用者採用的是 Android Gradle 外掛程式,這對他們而言將是最簡單的程式庫使用方式。
原生資料庫可以透過 AGP 封裝為 AAR。如果您已透過 externalNativeBuild 建構程式庫,這便是最簡單的方法。
非 AGP 建構可以使用 ndkport,或按照
Prefab 說明文件,建立 AAR 的 prefab/
子目錄。
包含 JNI 程式庫的 Java 中介軟體
包含 JNI 程式庫的 Java 程式庫 (也就是包含
jniLibs
),需要注意的是,這些程式庫包含的 JNI 程式庫不會
會與使用者應用程式中的其他程式庫衝突。舉例來說,如果 AAR 包含
libc++_shared.so
,但 libc++_shared.so
版本與應用程式不同
,系統只會將其中一個應用程式安裝至 APK,而這可能導致不穩定
行為
最可靠的解決方案是確保 Java 程式庫中的 JNI 程式庫不超過一個 (這同樣適用於應用程式)。包含 STL 在內的所有依附元件都應該以靜態方式連結至實作程式庫,並且應該使用版本指令碼強制執行 ABI 介面。例如,包含 JNI 程式庫 libfooimpl.so
的 Java 程式庫 com.example.foo
,應使用下列版本指令碼:
LIBFOOIMPL {
global:
JNI_OnLoad;
local:
*;
};
這個範例按照 JNI 提示中的說明,透過 JNI_OnLoad
使用 registerNatives
來確保盡量不公開 ABI 介面,同時盡可能縮短程式庫載入時間。