Triển khai thư viện SDK Java

Nền tảng Android chứa một số lượng lớn thư viện Java dùng chung có thể tuỳ ý được đưa vào đường dẫn lớp của ứng dụng Thẻ <uses-library> trong tệp kê khai ứng dụng. Đường liên kết ứng dụng dựa trên các thư viện này, vì vậy hãy xử lý chúng như những phần còn lại của API Android về khả năng tương thích, đánh giá API và hỗ trợ công cụ. Tuy nhiên, xin lưu ý hầu hết các thư viện không có những tính năng này.

Loại mô-đun java_sdk_library giúp quản lý thư viện loại này. Nhà sản xuất thiết bị có thể sử dụng cơ chế này cho riêng họ thư viện Java dùng chung, để duy trì khả năng tương thích ngược cho các API của chúng. Nếu nhà sản xuất thiết bị sử dụng thư viện Java dùng chung của riêng họ thông qua <uses-library> thay vì đường dẫn lớp khởi động, java_sdk_library có thể xác minh rằng các thư viện Java đó Ổn định API.

java_sdk_library triển khai các API SDK không bắt buộc để sử dụng của chúng tôi. Các thư viện được triển khai thông qua java_sdk_library trong tệp bản dựng (Android.bp) thực hiện các thao tác sau:

  • Các thư viện mã giả lập được tạo để bao gồm stubs, stubs.systemstubs.test. Các các thư viện mã giả lập được tạo bằng cách nhận dạng @hide, Chú thích @SystemApi@TestApi.
  • java_sdk_library quản lý các tệp thông số kỹ thuật của API (chẳng hạn như current.txt) trong một thư mục con API. Các tệp này được kiểm tra dựa trên mã mới nhất để đảm bảo rằng chúng các phiên bản hiện tại. Nếu không, bạn sẽ nhận được một thông báo lỗi cho biết giải thích cách cập nhật chúng. Xem xét thủ công tất cả các thay đổi đối với nội dung cập nhật đảm bảo rằng chúng đáp ứng kỳ vọng của bạn.

    Để cập nhật tất cả API, hãy dùng m update-api. Để xác minh rằng một API đã cập nhật, sử dụng m checkapi.
  • Các tệp thông số kỹ thuật API được đối chiếu với phát hành phiên bản Android để đảm bảo rằng API này có khả năng tương thích ngược với các bản phát hành trước đó. Các mô-đun java_sdk_library được cung cấp như một phần của AOSP, hãy đặt các phiên bản được phát hành trước đó vào prebuilts/sdk/<latest number>
  • Đối với các bước kiểm tra tệp thông số kỹ thuật API, bạn có thể một trong ba điều sau:
    • Tiếp tục các bước kiểm tra. (Không làm gì cả.)
    • Tắt các bước kiểm tra bằng cách thêm đoạn mã sau vào java_sdk_library:
      unsafe_ignore_missing_latest_api: true,
    • Cung cấp API trống cho các mô-đun java_sdk_library mới bằng cách tạo tệp văn bản trống có tên là module_name.txt trong thư mục version/scope/api.
  • Nếu bạn cài đặt thư viện triển khai cho thời gian chạy, tệp XML sẽ được tạo và cài đặt.

Cách hoạt động của java_sdk_library

java_sdk_library có tên là X sẽ tạo nội dung sau:

  1. Hai bản sao của thư viện triển khai: một thư viện có tên là X và một thiết bị khác có tên là X.impl. Đã cài đặt thư viện X trên thiết bị. Thư viện X.impl chỉ có khi có quyền truy cập rõ ràng vào các mô-đun khác cần có thư viện triển khai, chẳng hạn như để sử dụng trong kiểm thử. Lưu ý rằng hiếm khi cần quyền truy cập rõ ràng.
  2. Bạn có thể bật và tắt phạm vi để tuỳ chỉnh quyền truy cập. (Tương tự như Java đối tượng sửa đổi truy cập từ khoá, phạm vi công khai cung cấp phạm vi truy cập rộng; một phạm vi kiểm thử chứa các API chỉ được dùng trong kiểm thử.) Đối với mỗi phạm vi đã bật, thư viện tạo các đoạn mã sau:
    • Một mô-đun nguồn mã giả lập (thuộc loại mô-đun droidstubs) – sử dụng nguồn triển khai và xuất ra một tập hợp các nguồn mã giả lập cùng với tệp thông số kỹ thuật API.
    • Thư viện mã giả lập (thuộc loại mô-đun java_library) – là phiên bản được biên dịch của mã giả lập. Các lib dùng để biên dịch này không phải là giống như các mã được cung cấp cho java_sdk_library. Điều này đảm bảo Thông tin triển khai không rò rỉ vào các mã API.
    • Nếu bạn cần thêm thư viện để biên dịch mã giả lập, hãy sử dụng stub_only_libsstub_only_static_libs để cung cấp chúng.

Nếu java_sdk_library được gọi là "X" và đang được được biên dịch dựa trên "X", luôn gọi tên đó theo cách đó và không sửa đổi nó. Bản dựng sẽ chọn một thư viện phù hợp. Để đảm bảo rằng bạn có thư viện thích hợp nhất, hãy kiểm tra mã giả lập của bạn để xem liệu bản dựng có được đưa ra hay không . Thực hiện mọi sửa đổi cần thiết theo hướng dẫn này:

  • Xác minh rằng bạn có thư viện phù hợp bằng cách xem trên dòng lệnh và kiểm tra mã giả lập (stub) nào được liệt kê ở đó để xác định phạm vi của bạn:
    • Phạm vi quá rộng: Thư viện phụ thuộc cần một phạm vi API nhất định. Nhưng bạn sẽ thấy các API có trong thư viện nằm ngoài phạm vi đó, chẳng hạn như system API có trong API công khai.
    • Phạm vi quá hẹp: Thư viện phụ thuộc không có quyền truy cập vào tất cả các thư viện cần thiết. Ví dụ: thư viện phụ thuộc cần sử dụng thuộc tính system API nhưng lại nhận API công khai. Điều này thường dẫn đến lỗi biên dịch do thiếu API cần thiết.
  • Để sửa thư viện này, bạn chỉ cần làm một trong các thao tác sau:
    • Thay đổi sdk_version để chọn phiên bản bạn cần. HOẶC
    • Chỉ định rõ thư viện phù hợp, chẳng hạn như <X>.stubs hoặc <X>.stubs.system.

Mức sử dụng java_sdk_library X

Thư viện triển khai X được dùng khi được tham chiếu từ apex.java_libs Tuy nhiên, do giới hạn của Soong, khi thư viện X được tham chiếu từ một mô-đun java_sdk_library khác trong cùng thư viện APEX, X.impl một cách rõ ràng Bạn phải sử dụng, không phải thư viện X.

Khi java_sdk_library được tham chiếu từ nơi khác, một mã giả lập (stub) thư viện khác được sử dụng. Thư viện mã giả lập được chọn theo chế độ cài đặt thuộc tính sdk_version của mô-đun. Ví dụ: một mô-đun chỉ định sdk_version: "current" sử dụng các mã giả lập công khai, trong khi một mô-đun chỉ định sdk_version: "system_current" sẽ sử dụng mã giả lập hệ thống. Nếu không tìm được kết quả trùng khớp hoàn toàn, thì thư viện mã giả lập gần nhất sẽ nhận được đã sử dụng. java_sdk_library chỉ cung cấp API công khai sẽ cung cấp mã giả lập công khai cho mọi người.

Quy trình xây dựng với thư viện SDK Java
Hình 1. Quy trình xây dựng với thư viện SDK Java

Ví dụ và nguồn

Thuộc tính srcsapi_packages phải xuất hiện trong java_sdk_library.

java_sdk_library {
        name: "com.android.future.usb.accessory",
        srcs: ["src/**/*.java"],
        api_packages: ["com.android.future.usb"],
    }

AOSP đề xuất (nhưng không bắt buộc) java_sdk_library mới đó bật các phiên bản thể hiện rõ ràng các phạm vi API mà chúng muốn sử dụng. Bạn cũng có thể (không bắt buộc) di chuyển thực thể java_sdk_library hiện có sang bật rõ ràng các phạm vi API mà họ sẽ sử dụng:

java_sdk_library {
         name: "lib",
         public: {
           enabled: true,
         },
         system: {
           enabled: true,
         },
         …
    }

Để định cấu hình thư viện impl dùng cho thời gian chạy, hãy sử dụng tất cả các thuộc tính java_library thông thường, chẳng hạn như hostdex, compile_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,
    }

Để định cấu hình các thư viện mã giả lập, hãy sử dụng các thuộc tính sau:

  • merge_annotations_dirsmerge_inclusion_annotations_dirs.
  • api_srcs: Danh sách các tệp nguồn (không bắt buộc) là một phần của API nhưng không thuộc thư viện thời gian chạy.
  • stubs_only_libs: Danh sách các thư viện Java nằm trong đường dẫn lớp khi tạo mã giả lập.
  • hidden_api_packages: Danh sách các tên gói bắt buộc phải ẩn khỏi API.
  • droiddoc_options: Đối số bổ sung cho metalava.
  • droiddoc_option_files: Liệt kê các tệp có thể tham chiếu từ trong droiddoc_options bằng $(location <label>), trong đó <file> là một mục trong danh sách.
  • annotations_enabled.

java_sdk_library là một java_library, không phải là Mô-đun droidstubs và do đó không hỗ trợ tất cả droidstubs các thuộc tính. Ví dụ sau được lấy từ bản dựng thư viện 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,
    }

Duy trì khả năng tương thích ngược

Hệ thống xây dựng kiểm tra xem các API có được duy trì trở về trước hay không bằng cách so sánh các tệp API mới nhất với Các tệp API tại thời điểm tạo bản dựng. java_sdk_library thực hiện việc kiểm tra khả năng tương thích bằng cách sử dụng thông tin do prebuilt_apis cung cấp. Tất cả thư viện được tạo bằng java_sdk_library đều phải có tệp API trong phiên bản mới nhất của api_dirs trong prebuilt_apis. Khi bạn phát hành phiên bản, API sẽ liệt kê các tệp và mã giả lập các thư viện có thể lấy được bằng bản dựng dist bằng PRODUCT=sdk_phone_armv7-sdk.

Thuộc tính api_dirs là danh sách các thư mục phiên bản API trong prebuilt_apis. Các thư mục phiên bản API phải được đặt ở cấp thư mục Android.bp.

prebuilt_apis {
       name: "foo",
       api_dirs: [
           "1",
           "2",
             ....
           "30",
           "current",
       ],
    }

Định cấu hình các thư mục bằng version/scope/api/ trong thư mục tạo sẵn. version tương ứng với cấp độ API và scope xác định cho dù thư mục là công khai, hệ thống hay kiểm thử.

  • version/scope chứa các thư viện Java.
  • version/scope/api chứa API .txt tệp. Tạo tệp văn bản trống có tên module_name.txtmodule_name-removed.txt tại đây.
     ├── 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