Android 平台包含大量的共享 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
。- 系统会对照最近发布的 Android 版本对 API 规范文件进行检查,以确保相应 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 的用法
实现库 X
会在从 apex.java_libs
引用后被使用。不过,由于 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
将为所有人提供公共存根。
![使用 Java SDK 库的构建流程](https://source.android.google.cn/static/docs/core/architecture/images/build-flow-java-lib.png?authuser=9&hl=sl)
示例和来源
java_sdk_library
中必须提供 srcs
和 api_packages
属性。
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 库 build 文件。
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 文件。
当您发布版本时,可以使用 PRODUCT=sdk_phone_armv7-sdk
通过 dist build 获取 API 列表文件和存根库。
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