實作Java SDK函式庫

Android 平台包含大量共用 Java 函式庫,可以選擇將這些函式庫包含在應用程式清單中帶有<uses-library>標記的應用程式的類別路徑中。應用程式連結到這些庫,因此在相容性、API 審查和工具支援方面將它們視為 Android API 的其餘部分。但請注意,大多數函式庫沒有這些功能。

java_sdk_library模組類型有助於管理此類庫。設備製造商可以將此機制用於自己的共享 Java 庫,以保持其 API 的向後相容性。如果裝置製造商透過<uses-library>標記而不是引導類別路徑使用自己的共用 Java 函式庫,則java_sdk_library可以驗證這些 Java 函式庫是否是 API 穩定的。

java_sdk_library實作可選的 SDK API 供應用程式使用。透過建置檔案 ( Android.bp ) 中的java_sdk_library實現的庫執行以下操作:

  • 產生的存根庫包括stubsstubs.systemstubs.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 的工作原理

名為Xjava_sdk_library建立以下內容:

  1. 實作庫的兩個副本:一個名為X函式庫,另一個名為X.impl 。庫X安裝在設備上。只有當其他模組需要明確存取實作庫(例如用於測試時)時,庫X.impl才存在。請注意,很少需要明確訪問。
  2. 可以啟用和停用範圍來自訂存取。 (與 Java 關鍵字存取修飾符類似,公共作用域提供廣泛的存取權限;測試作用域包含僅在測試中使用的 API。)對於每個啟用的作用域,該程式庫會建立以下內容:
    • 存根模組( droidstubs模組類型)- 使用實作來源並輸出一組存根以及 API 規格文件。
    • 存根庫( java_library模組類型) - 是存根的編譯版本。用於編譯它的函式庫與提供給java_sdk_library的函式庫不同,這確保了實作細節不會洩漏到 API 存根中。
    • 如果您需要其他函式庫來編譯存根,請使用stub_only_libsstub_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將為每個人提供公共存根。

使用 Java SDK 庫建立流程
圖 1.使用 Java SDK 函式庫的建置流程

範例和來源

srcsapi_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屬性,例如hostdexcompile_dexerrorprone

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_dirsmerge_inclusion_annotations_dirs
  • api_srcs :屬於 API 的一部分但不屬於執行時間庫的可選來源檔案清單。
  • stubs_only_libs :建構存根時位於類別路徑中的 Java 函式庫的清單。
  • hidden_api_packages :必須對 API 隱藏的套件名稱清單。
  • droiddoc_optionsmetalava的附加參數。
  • 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 檔案。當您發布版本時,可以使用 dist build 並使用PRODUCT=sdk_phone_armv7-sdk來取得 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 .txtmodule_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