تنفيذ مكتبة حزمة تطوير البرامج (SDK) لنظام Java

يحتوي نظام Android الأساسي على عدد كبير من مكتبات Java المشترَكة التي يمكن تضمينها اختياريًا في مسار تحميل التطبيقات باستخدام علامة <uses-library> في بيان التطبيق. ترتبط التطبيقات بهذه المكتبات، لذا يجب التعامل معها مثل باقي واجهات برمجة تطبيقات Android من حيث التوافق ومراجعة واجهات برمجة التطبيقات ودعم الأدوات. يُرجى العلم، مع ذلك، أنّ معظم المكتبات لا تتضمّن هذه الميزات.

يساعد نوع الوحدة java_sdk_library في إدارة المكتبات من هذا النوع. يمكن لصنّاع الأجهزة استخدام هذه الآلية ل مكتبات Java المشتركة الخاصة بهم، وذلك للحفاظ على التوافق مع الإصدارات القديمة من واجهات برمجة التطبيقات. إذا كان المصنّعون يستخدمون مكتبات Java المشتركة الخاصة بهم من خلال علامة <uses-library> بدلاً من مسار bootclass، يمكن لـ java_sdk_library التحقّق من أنّ مكتبات Java هذه مستقرة من حيث واجهة برمجة التطبيقات.

ينفذ java_sdk_library واجهات برمجة تطبيقات حِزم تطوير البرامج (SDK) الاختيارية لاستخدامها في التطبيقات. تُجري المكتبات التي يتم تنفيذها من خلال java_sdk_library فيملف الإنشاء (Android.bp) العمليات التالية:

  • يتم إنشاء مكتبات العناصر النائبة لتضمين stubs stubs.system وstubs.test. يتم إنشاء مكتبات العناصر النموذجية هذه من خلال التعرّف على التعليقات التوضيحية @hide @SystemApi و@TestApi.
  • يدير java_sdk_library ملفات مواصفات واجهة برمجة التطبيقات (مثل current.txt) في دليل فرعي لواجهة برمجة التطبيقات. تتم مراجعة هذه الملفات مقارنةً بأحدث رمز لضمان أنّها تمثل الإصدارات الأحدث. إذا لم تكن كذلك، ستظهر لك رسالة خطأ توضّح كيفية تعديلها. راجِع يدويًا جميع التغييرات التي تم إجراؤها على التعديلات للتأكّد من أنّها تتوافق مع توقعاتك.

    لتحديث جميع واجهات برمجة التطبيقات، استخدِم m update-api. للتأكّد من تحديث واجهة برمجة التطبيقات، استخدِم m checkapi.
  • يتم التحقّق من ملفات مواصفات واجهة برمجة التطبيقات مقارنةً بأحدث إصدارات Android التي تم نشرها للتأكّد من توافق واجهة برمجة التطبيقات مع الإصدارات السابقة. تضع وحدات java_sdk_library المقدَّمة كجزء من AOSP إصداراتها التي تم إصدارها سابقًا في prebuilts/sdk/<latest number>.
  • في ما يتعلّق بعمليات التحقّق من ملفات مواصفات واجهة برمجة التطبيقات، يمكنك تنفيذ إجراء واحد من الإجراءات الثلاثة التالية:
    • اسمح بمتابعة عمليات التحقّق. (لا داعي لاتّخاذ أي إجراء).
    • أوقِف عمليات التحقّق من خلال إضافة ما يلي إلى java_sdk_library:
      unsafe_ignore_missing_latest_api: true,
    • قدِّم واجهات برمجة تطبيقات فارغة لنماذج java_sdk_library الجديدة عن طريق إنشاء ملفات نصية فارغة باسم module_name.txt في الدليل version/scope/api.
  • في حال تثبيت مكتبة التنفيذ لوقت التشغيل، يتم إنشاء ملف XML وتثبيته.

آلية عمل java_sdk_library

يُنشئ java_sdk_library باسم X ما يلي:

  1. نسختان من مكتبة التنفيذ: مكتبة باسم X وأخرى باسم X.impl. تم تثبيت المكتبة X على الجهاز. لا تتوفّر المكتبة X.impl إلا إذا كانت الوحدات الأخرى بحاجة إلى إذن وصول صريح إلى مكتبة التنفيذ، مثلاً لاستخدامها في الاختبار. يُرجى العلم أنّه نادرًا ما يكون الوصول الصريح مطلوبًا.
  2. يمكن تفعيل النطاقات وإيقافها لتخصيص أذونات الوصول. (على غرار مُعدِّلات Java للوصول إلى الكلمات الرئيسية، يقدّم النطاق العام مجموعة كبيرة من أذونات الوصول. يحتوي نطاق الاختبار على واجهات برمجة التطبيقات المستخدَمة في الاختبار فقط). لكل نطاق مفعّل، تنشئ مكتبة ما يلي:
    • وحدة مصدر العناصر النائبة (من نوع وحدة droidstubs): تستخدِم مصدر التنفيذ وتُخرج مجموعة من مصادر العناصر النائبة مع الملف الذي يحدّد مواصفات واجهة برمجة التطبيقات.
    • مكتبة العناصر النائبة (من نوع وحدة java_library) هي النسخة المجمّعة من العناصر النائبة. إنّ المكتبات المستخدَمة لتجميع هذا الرمز البرمجي ليست هي نفسها المكتبات المقدَّمة إلى java_sdk_library، ما يضمن عدم تسرُّب تفاصيل التنفيذ إلى نماذج واجهة برمجة التطبيقات.
    • إذا كنت بحاجة إلى مكتبات إضافية لتجميع العناصر المصغّرة، استخدِم السمتَين stub_only_libs وstub_only_static_libs لإتاحتها.

إذا كان اسم java_sdk_library هو "X"، ويتم compiling وفقًا للاسم "X"، يجب الإشارة إليه دائمًا بهذه الطريقة وعدم تعديله. سيختار الإصدار مكتبة مناسبة. للتأكّد من حصولك على المكتبة الأنسب، عليك فحص العناصر المصغّرة لمعرفة ما إذا كان الإنشاء قد أدّى إلى ظهور أخطاء. يمكنك إجراء أي تصحيحات ضرورية باستخدام هذه الإرشادات:

  • تأكَّد من توفّر مكتبة مناسبة من خلال البحث في سطر الأوامر وexamined فحص العناصر التي تم إدراجها هناك لتحديد نطاقك:
    • النطاق واسع جدًا: تحتاج المكتبة المُستندة إلى نطاق معيّن من واجهات برمجة التطبيقات. ولكن تظهر لك واجهات برمجة تطبيقات مضمّنة في المكتبة لا تندرج ضمن هذا النطاق، مثل واجهات برمجة تطبيقات النظام المضمّنة مع واجهات برمجة التطبيقات المتاحة للجميع.
    • النطاق ضيق جدًا: لا يمكن للمكتبة المُستندة الوصول إلى كل مكتبة مطلوبة. على سبيل المثال، تحتاج المكتبة المُعتمَدة إلى استخدام واجهة برمجة تطبيقات النظام، ولكنها تحصل على واجهة برمجة التطبيقات المتاحة للجميع بدلاً من ذلك. يؤدي ذلك عادةً إلى خطأ compiling (الترجمة والربط) بسبب عدم توفّر واجهات برمجة التطبيقات المطلوبة.
  • لحلّ مشكلة المكتبة، عليك تنفيذ إجراء واحد فقط مما يلي:
    • غيِّر الرمز 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 الذي يوفّر واجهة برمجة تطبيقات عامة فقط سيوفّر العناصر النائبة العامة للجميع.

إنشاء مسار باستخدام مكتبة 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. يمكنك أيضًا (اختياريًا) نقل نُسخ java_sdk_library الحالية لأجل تفعيل نطاقات واجهة برمجة التطبيقات التي ستستخدمها بشكل صريح:

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: قائمة الملفات المصدر الاختيارية التي تشكّل جزءًا من واجهة برمجة التطبيقات ولكنها ليست جزءًا من مكتبة وقت التشغيل
  • stubs_only_libs: قائمة مكتبات Java المتوفّرة في ملف ملف مسار تحميل الفئات عند إنشاء نماذج العناصر
  • hidden_api_packages: قائمة أسماء الحِزم التي يجب إخفاؤها من واجهة برمجة التطبيقات
  • 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,
    }

الحفاظ على التوافق مع الإصدارات القديمة

يتحقّق نظام الإنشاء مما إذا كانت واجهات برمجة التطبيقات قد حافظت على التوافق مع الإصدارات القديمة من خلال مقارنة أحدث ملفات واجهات برمجة التطبيقات بملفات واجهات برمجة التطبيقات التي تم إنشاؤها في وقت الإنشاء. يُجري java_sdk_library عملية التحقّق من التوافق باستخدام المعلومات المقدَّمة من prebuilt_apis. يجب أن تحتوي جميع المكتبات التي تم إنشاؤها باستخدام java_sdk_library على ملفات واجهة برمجة التطبيقات في أحدث إصدار من api_dirs في prebuilt_apis. عند إصدار الإصدار، تُدرج واجهة برمجة التطبيقات الملفات والعناصر المرجعية ويمكن الحصول على المكتبات باستخدام عملية إنشاء dist مع PRODUCT=sdk_phone_armv7-sdk.

الموقع api_dirs هو قائمة بأدلة إصدارات واجهة برمجة التطبيقات في prebuilt_apis. يجب أن تكون أدلة إصدارات واجهة برمجة التطبيقات متوفّرة على مستوى الدليل Android.bp.

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

اضبط الأدلة باستخدام بنية version/scope/api/ ضمن دليل prebuilts. يتوافق العنصر version مع مستوى واجهة برمجة التطبيقات، ويحدّد العنصر scope ما إذا كان الدليل متاحًا للجميع أو للنظام أو للاختبار.

  • يحتوي version/scope على مكتبات Java.
  • يحتوي version/scope/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