Android 平台包含大量共享 Java 庫,可以選擇將這些 Java 庫包含在應用程序清單中帶有<uses-library>
標記的應用程序的類路徑中。應用程序鏈接到這些庫,因此在兼容性、API 審查和工具支持方面將它們視為 Android 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
。這些存根庫是通過識別@hide
、@SystemApi
和@TestApi
註釋來創建的。 -
java_sdk_library
管理 API 子目錄中的 API 規範文件(例如current.txt
)。這些文件會根據最新代碼進行檢查,以確保它們是最新版本。如果不是,您會收到一條錯誤消息,說明如何更新它們。手動查看所有更新更改以確保它們符合您的期望。
要更新所有 API,請使用m update-api
。要驗證 API 是否是最新的,請使用m checkapi
。 - API 規範文件會根據最新發布的 Android 版本進行檢查,以確保 API 向後兼容早期版本。作為 AOSP 的一部分提供的
java_sdk_library
模塊將其先前發布的版本放置在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_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 的限制,當從同一個 APEX 庫中的另一個java_sdk_library
模塊引用庫X
時,必須明確使用X.impl
而不是庫X
。
當從其他地方引用java_sdk_library
時,將使用存根庫。根據依賴模塊的sdk_version
屬性設置選擇存根庫。例如,指定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, }
要配置存根庫,請使用以下屬性:
-
merge_annotations_dirs
和merge_inclusion_annotations_dirs
。 -
api_srcs
:作為 API 一部分但不屬於運行時庫的可選源文件的列表。 -
stubs_only_libs
:構建存根時類路徑中的 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 列表文件和存根庫可以通過 dist build 和PRODUCT=sdk_phone_armv7-sdk
獲得。
api_dirs
屬性是prebuilt_apis
中 API 版本目錄的列表。 API 版本目錄必須位於Android.bp
目錄級別。
prebuilt_apis { name: "foo", api_dirs: [ "1", "2", .... "30", "current", ], }
配置prebuilts目錄下的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