ใช้ไลบรารี Java SDK

แพลตฟอร์ม Android มีไลบรารี Java ที่แชร์จำนวนมาก ซึ่งจะรวมไว้ใน classpath ของแอปที่มีแท็ก <uses-library> ในไฟล์ Manifest ของแอปหรือไม่ก็ได้ แอปจะลิงก์กับไลบรารีเหล่านี้ ดังนั้นให้ถือว่าไลบรารีเหล่านี้เหมือนกับ API อื่นๆ ของ Android ในแง่ของความเข้ากันได้ การตรวจสอบ API และการรองรับเครื่องมือ อย่างไรก็ตาม โปรดทราบว่าคลังส่วนใหญ่ไม่มีฟีเจอร์เหล่านี้

ประเภทโมดูล java_sdk_library ช่วยจัดการไลบรารีประเภทนี้ ผู้ผลิตอุปกรณ์สามารถใช้กลไกนี้กับไลบรารี Java ที่แชร์ของตนเองเพื่อรักษาความเข้ากันได้แบบย้อนหลังสำหรับ API ของตน หากผู้ผลิตอุปกรณ์ใช้ไลบรารี Java ที่แชร์ของตนเองผ่านแท็ก <uses-library> แทนเส้นทางบูตคลาส java_sdk_library จะยืนยันได้ว่าไลบรารี Java เหล่านั้นเป็น API ที่เสถียร

java_sdk_library ใช้ API ของ SDK ที่ไม่บังคับเพื่อให้แอปใช้ ไลบรารีที่ติดตั้งใช้งานผ่าน java_sdk_library ในไฟล์บิลด์ (Android.bp) จะดำเนินการต่อไปนี้

  • ระบบจะสร้างไลบรารีสตั๊บเพื่อรวม stubs, stubs.system และ stubs.test ไลบรารีสแต็บเหล่านี้สร้างขึ้นโดยการจดจำคำอธิบายประกอบ @hide, @SystemApi และ @TestApi
  • java_sdk_library จะจัดการไฟล์ข้อกำหนด API (เช่น current.txt) ในไดเรกทอรีย่อย API ระบบจะตรวจสอบไฟล์เหล่านี้เทียบกับโค้ดล่าสุดเพื่อให้แน่ใจว่าเป็นเวอร์ชันล่าสุด หากไม่ คุณจะได้รับข้อความแสดงข้อผิดพลาดที่อธิบายวิธีอัปเดต ตรวจสอบการเปลี่ยนแปลงการอัปเดตทั้งหมดด้วยตนเองเพื่อให้แน่ใจว่าการเปลี่ยนแปลงตรงกับที่คุณคาดไว้

    หากต้องการอัปเดต API ทั้งหมด ให้ใช้ m update-api หากต้องการยืนยันว่า API เป็นเวอร์ชันล่าสุด ให้ใช้ m checkapi
  • ระบบจะตรวจสอบไฟล์ข้อกำหนดของ API กับ Android เวอร์ชันที่เผยแพร่ล่าสุดเพื่อให้แน่ใจว่า API ใช้งานร่วมกับรุ่นก่อนหน้าได้ โมดูล java_sdk_library ที่ให้มาเป็นส่วนหนึ่งของ AOSP จะวางเวอร์ชันที่เผยแพร่ก่อนหน้านี้ไว้ใน prebuilts/sdk/<latest number>
  • คุณสามารถดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้สำหรับการตรวจสอบไฟล์ข้อกำหนด API
    • อนุญาตให้ดำเนินการตรวจสอบต่อ (ไม่ต้องดำเนินการใดๆ)
    • ปิดใช้การตรวจสอบโดยเพิ่มรายการต่อไปนี้ลงใน java_sdk_library
      unsafe_ignore_missing_latest_api: true,
    • ระบุ API ว่างสำหรับข้อบังคับ java_sdk_library ใหม่โดยสร้างไฟล์ข้อความว่างชื่อ module_name.txt ในไดเรกทอรี version/scope/api
  • หากติดตั้งไลบรารีการใช้งานสําหรับรันไทม์แล้ว ระบบจะสร้างและติดตั้งไฟล์ XML

วิธีการทำงานของ java_sdk_library

java_sdk_library ชื่อ X จะสร้างสิ่งต่อไปนี้

  1. ไลบรารีการใช้งาน 2 เล่ม ได้แก่ ไลบรารีชื่อ X และอีกเล่มชื่อ X.impl ติดตั้งคลัง X ในอุปกรณ์แล้ว ไลบรารี X.impl จะแสดงขึ้นก็ต่อเมื่อโมดูลอื่นๆ ต้องการการเข้าถึงไลบรารีการติดตั้งใช้งานอย่างชัดเจน เช่น เพื่อใช้ในการทดสอบ โปรดทราบว่าแทบไม่จําเป็นต้องใช้การเข้าถึงที่ชัดเจน
  2. คุณเปิดและปิดใช้ขอบเขตเพื่อปรับแต่งการเข้าถึงได้ (คล้ายกับตัวแก้ไขการเข้าถึงคีย์เวิร์ดของ 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 เมื่อมีการอ้างอิงไลบรารี X จากโมดูล java_sdk_library อื่นภายในไลบรารี APEX เดียวกัน คุณต้องใช้ X.impl อย่างชัดแจ้ง ไม่ใช่ไลบรารี X

เมื่อมีการอ้างอิง java_sdk_library จากที่อื่น ระบบจะใช้ไลบรารีสแต็บ ระบบจะเลือกคลังสตับตามการตั้งค่าพร็อพเพอร์ตี้ sdk_version ของโมดูลที่เกี่ยวข้อง เช่น โมดูลที่ระบุ sdk_version: "current" จะใช้สแต็บสาธารณะ ส่วนโมดูลที่ระบุ sdk_version: "system_current" จะใช้สแต็บระบบ หากไม่พบรายการที่ตรงกันทั้งหมด ระบบจะใช้ไลบรารีสแต็บที่ใกล้เคียงที่สุด java_sdk_library ที่มีเฉพาะ API สาธารณะจะจัดหาสแต็บสาธารณะให้ทุกคน

ขั้นตอนการสร้างด้วยไลบรารี Java SDK
รูปที่ 1 ขั้นตอนการสร้างด้วยไลบรารี Java SDK

ตัวอย่างและแหล่งที่มา

พร็อพเพอร์ตี้ 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: แสดงรายการไฟล์ที่อ้างอิงได้จากภายใน droiddoc_options โดยใช้ $(location <label>) โดยที่ <file> คือรายการในลิสต์
  • annotations_enabled

java_sdk_library เป็น java_library แต่ไม่ใช่ข้อบังคับของ droidstubs จึงไม่รองรับพร็อพเพอร์ตี้ droidstubs ทั้งหมด ตัวอย่างต่อไปนี้นำมาจากไฟล์android.test.mock library 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 ต้องมีไฟล์ API ใน api_dirs เวอร์ชันล่าสุดใน prebuilt_apis เมื่อคุณเผยแพร่เวอร์ชันแล้ว ไฟล์และไลบรารีของ API รายการต่างๆ จะพร้อมใช้งานในบิลด์ dist ด้วย PRODUCT=sdk_phone_armv7-sdk

พร็อพเพอร์ตี้ api_dirs คือรายการไดเรกทอรีเวอร์ชัน API ใน prebuilt_apis ไดเรกทอรีเวอร์ชัน 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