Android 平台包含大量共用的 Java 程式庫,您可以選擇在應用程式資訊清單中使用 <uses-library> 標記,將這些程式庫納入應用程式的 classpath。應用程式會連結至這些程式庫,因此請將這些程式庫視為其他 Android API,以相容性、API 審查和工具支援為依據。不過,請注意,大多數程式庫都沒有這些功能。
java_sdk_library 模組類型可協助管理這類程式庫。裝置製造商可以使用這個機制為自家的共用 Java 程式庫,維持 API 的向下相容性。如果裝置製造商透過 <uses-library> 標記 (而非 bootclass 路徑) 使用自己的共用 Java 程式庫,java_sdk_library 就能驗證這些 Java 程式庫是否為 API 穩定。
java_sdk_library 會導入供應用程式使用的選用 SDK API。在建構檔案 (Android.bp) 中透過 java_sdk_library 實作的程式庫會執行下列作業:
- 系統會產生包含
stubs、stubs.system和stubs.test的 Stub 程式庫。這些 Stub 程式庫是透過辨識@hide、@SystemApi和@TestApi註解而建立。 java_sdk_library會管理 API 子目錄中的 API 規格檔案 (例如current.txt)。系統會根據最新程式碼檢查這些檔案,確保檔案為最新版本。如果不是,您會收到錯誤訊息,說明如何更新。手動檢查所有更新變更,確保這些變更符合您的預期。
如要更新所有 API,請使用m update-api。如要確認 API 是否為最新版本,請使用m checkapi。- 系統會根據最近發布的 Android 版本檢查 API 規格檔案,確保 API 與舊版版本相容。提供的
java_sdk_library模組是 Android 開放原始碼計畫的一部分,會將先前發布的版本放入prebuilts/sdk/<latest number>。 - 針對 API 規格檔案檢查,您可以執行下列三項操作中的一項:
- 允許檢查程序繼續進行。(請勿採取任何行動)。
- 如要停用檢查功能,請在
java_sdk_library中加入以下內容:
unsafe_ignore_missing_latest_api: true, - 在
version/scope/api目錄中建立名為module_name.txt的空白文字檔案,為新的java_sdk_library模組提供空白 API。 - 如果已安裝執行階段的實作程式庫,系統就會產生並安裝 XML 檔案。
java_sdk_library 的運作方式
名為 X 的 java_sdk_library 會建立下列項目:
- 實作程式庫的兩個副本:一個程式庫名為
X,另一個名為X.impl。程式庫X已安裝在裝置上。只有在其他模組需要明確存取實作程式庫 (例如用於測試) 時,程式庫X.impl才會存在。請注意,您很少需要明確存取權。 - 您可以啟用及停用權限範圍,自訂存取權。(與 Java 關鍵字存取修飾符類似,公開範圍提供廣泛的存取權;測試範圍則包含僅用於測試的 API)。針對每個已啟用的範圍,程式庫會建立下列項目:
- 存根來源模組 (
droidstubs模組類型):會使用實作來源,並輸出一系列存根來源和 API 規格檔案。 - 存根程式庫 (
java_library模組類型) - 是存根程式的編譯版本。用於編譯的程式庫與提供給java_sdk_library的程式庫不同,可確保實作詳細資料不會流入 API 虛設常式。 - 如果您需要額外的程式庫來編譯 Stub,請使用
stub_only_libs和stub_only_static_libs屬性提供這些程式庫。
如果 java_sdk_library 稱為「X」,且以「X」編譯,請一律以這種方式參照,且不要修改。系統會選取適當的程式庫。為確保您擁有最合適的程式庫,請檢查您的虛設檔,看看是否有建構引入的錯誤。請按照下列指南進行必要修正:
- 請查看指令列,並檢查列出的哪些虛設檔可用於判斷範圍,藉此確認您是否有適當的程式庫:
- 範圍太廣:依附程式庫需要特定範圍的 API。但您會看到程式庫中包含的 API 超出該範圍,例如公開 API 中包含的系統 API。
- 範圍太狹窄:依附程式庫無法存取所有必要程式庫。舉例來說,依附程式庫需要使用系統 API,但卻取得公用 API。這通常會導致編譯錯誤,因為缺少必要的 API。
- 如要修正程式庫,請只執行下列一項操作:
- 變更
sdk_version即可選取所需的版本。或 - 明確指定適當的程式庫,例如
<X>.stubs或<X>.stubs.system。
java_sdk_library X 用法
當 apex.java_libs 參照實作程式庫 X 時,系統就會使用該程式庫。不過,由於 Soong 有限制,如果程式庫 X 是從同一個 APEX 程式庫中的其他 java_sdk_library 模組參照,則必須使用明確的 X.impl,而非程式庫 X。
當 java_sdk_library 從其他地方參照時,會使用 Stub 程式庫。系統會根據依附模組的 sdk_version 屬性設定,選取 Stub 程式庫。舉例來說,指定 sdk_version: "current" 的模組會使用公開存根節點,而指定 sdk_version: "system_current" 的模組會使用系統存根節點。如果找不到完全相符的結果,系統會使用最接近的輔助程式庫。只提供公開 API 的 java_sdk_library 會為所有人提供公開存根目錄。
範例和來源
srcs 和 api_packages 屬性「必須」出現在 java_sdk_library 中。
java_sdk_library { name: "com.android.future.usb.accessory", srcs: ["src/**/*.java"], api_packages: ["com.android.future.usb"], }
AOSP 建議 (但不強制規定) 新的 java_sdk_library 例項明確啟用所需的 API 範圍。您也可以 (選用) 遷移現有的 java_sdk_library 執行個體,明確啟用這些執行個體將使用的 API 範圍:
java_sdk_library { name: "lib", public: { enabled: true, }, system: { enabled: true, }, … }
如要設定用於執行階段的 impl 程式庫,請使用所有一般 java_library 屬性,例如 hostdex、compile_dex 和 errorprone。
java_sdk_library { name: "android.test.base", srcs: ["src/**/*.java"], errorprone: { javacflags: ["-Xep:DepAnn:ERROR"], }, hostdex: true, api_packages: [ "android.test", "android.test.suitebuilder.annotation", "com.android.internal.util", "junit.framework", ], compile_dex: true, }
如要設定 Stub 程式庫,請使用下列屬性:
merge_annotations_dirs和merge_inclusion_annotations_dirs。api_srcs:API 的選用來源檔案清單,但不屬於執行階段程式庫的一部分。stubs_only_libs:建構 Stub 時,位於路徑集的 Java 程式庫清單。hidden_api_packages:必須從 API 中隱藏的套件名稱清單。droiddoc_options:metalava 的額外引數。droiddoc_option_files:列出可透過$(location <label>)從droiddoc_options參照的檔案,其中<file>是清單中的項目。annotations_enabled。
java_sdk_library 是 java_library,但不是 droidstubs 模組,因此不支援所有 droidstubs 屬性。以下範例取自 android.test.mock 程式庫建構檔案。
java_sdk_library { name: "android.test.mock", srcs: [":android-test-mock-sources"], api_srcs: [ // Note: The following aren’t APIs of this library. Only APIs under the // android.test.mock package are taken. These do provide private APIs // to which android.test.mock APIs reference. These classes are present // in source code form to access necessary comments that disappear when // the classes are compiled into a Jar library. ":framework-core-sources-for-test-mock", ":framework_native_aidl", ], libs: [ "framework", "framework-annotations-lib", "app-compat-annotations", "Unsupportedappusage", ], api_packages: [ "android.test.mock", ], permitted_packages: [ "android.test.mock", ], compile_dex: true, default_to_stubs: true, }
維持回溯相容性
在建構期間,建構系統會將最新的 API 檔案與產生的 API 檔案進行比較,檢查 API 是否維持回溯相容性。java_sdk_library 會使用 prebuilt_apis 提供的資訊執行相容性檢查。所有使用 java_sdk_library 建構的程式庫,都必須在 prebuilt_apis 的最新版本中包含 api_dirs 的 API 檔案。發布版本時,API 會列出檔案和 Stub 程式庫,您可以使用 PRODUCT=sdk_phone_armv7-sdk 的 dist 建構來取得這些檔案。
api_dirs 屬性是 prebuilt_apis 中的 API 版本目錄清單。API 版本目錄必須位於 Android.bp 目錄層級。
prebuilt_apis { name: "foo", api_dirs: [ "1", "2", .... "30", "current", ], }
在預先建構目錄下,使用 version/scope/api/ 結構設定目錄。version 對應至 API 級別,而 scope 則定義目錄是公開、系統或測試。
version/scope包含 Java 程式庫。version/scope/api包含 API.txt檔案。請在此建立名為module_name.txt和module_name-removed.txt的空白文字檔案。├── 30 │ ├── public │ │ ├── api │ │ │ ├── android.test.mock-removed.txt │ │ │ └── android.test.mock.txt │ │ └── android.test.mock.jar │ ├── system │ │ ├── api │ │ │ ├── android.test.mock-removed.txt │ │ │ └── android.test.mock.txt │ │ └── android.test.mock.jar │ └── test │ ├── api │ │ ├── android.test.mock-removed.txt │ │ └── android.test.mock.txt │ └── android.test.mock.jar └── Android.bp