給中介軟體供應商的建議

發布使用 NDK 建構的中介軟體時會引發其他問題,但應用程式開發人員無需為此感到擔心。預建程式庫會為使用者提供一些實作選項。

選擇 API 級別和 NDK 版本

您的使用者使用的 minSdkVersion 版本不能比您低。如果使用者的應用程式需要在 API 21 上執行,您就無法針對 API 24 進行建構。您可以針對「低於」使用者的 API 級別建構程式庫,例如針對 API 16 建構程式庫,並保持與 API 21 使用者相容。

各 NDK 版本大多彼此相容,但版本間的變更偶爾會破壞相容性。如果您確定所有使用者都使用相同的 NDK 版本,則建議您也使用與使用者相同的版本,不然就是使用最新版本。

使用 STL

若您正在編寫 C++ 和使用 STL,並且要發布共用程式庫,那麼您在 libc++_sharedlibc++_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 介面,同時盡可能縮短程式庫載入時間。