دليل نقل البيانات إلى AndroidX Media3

يجب نقل التطبيقات التي تستخدم حاليًا مكتبة com.google.android.exoplayer2 المستقلة وandroidx.media إلى androidx.media3. يمكنك استخدام النص البرمجي لنقل البيانات لنقل ملفات إصدار gradle، وملفات المصدر Java وKotlin، وملفات تنسيق XML من ExoPlayer 2.19.1 إلى AndroidX Media3 1.1.1.

نظرة عامة

قبل نقل البيانات، يُرجى مراجعة الأقسام التالية للاطّلاع على مزيد من المعلومات حول مزايا واجهات برمجة التطبيقات الجديدة وواجهات برمجة التطبيقات المطلوب نقلها والمتطلبات الأساسية التي يجب أن يستوفيها مشروع تطبيقك.

أسباب النقل إلى Jetpack Media3

  • هذا هو المقر الجديد لمنصة ExoPlayer، بينما تم إيقاف com.google.android.exoplayer2.
  • الوصول إلى Player API في مختلف المكوّنات/العمليات من خلال MediaBrowser/MediaController.
  • استخدِم الإمكانات الإضافية لواجهة برمجة التطبيقات MediaSession وMediaController.
  • الإعلان عن إمكانات التشغيل باستخدام التحكّم الدقيق في الوصول
  • يمكنك تبسيط تطبيقك من خلال إزالة MediaSessionConnector و PlayerNotificationManager.
  • متوافقة مع الأنظمة القديمة مع واجهات برمجة التطبيقات للعميل المتوافق مع الوسائط (MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)

نقل واجهات برمجة التطبيقات للوسائط إلى AndroidX Media3

  • ExoPlayer وإضافاته
    يشمل ذلك جميع وحدات مشروع ExoPlayer القديم باستثناء وحدة mediasession التي تم إيقافها. يمكن نقل التطبيقات أو الوحدات بناءً على الحِزم في com.google.android.exoplayer2 باستخدام النص البرمجي لنقل البيانات.
  • MediaSessionConnector (استنادًا إلى حِزم androidx.media.* من androidx.media:media:1.4.3+)
    عليك إزالة MediaSessionConnector واستخدام androidx.media3.session.MediaSession بدلاً من ذلك.
  • MediaBrowserServiceCompat (استنادًا إلى حِزم androidx.media.* من androidx.media:media:1.4.3+)
    يمكنك نقل الفئات الفرعية من androidx.media.MediaBrowserServiceCompat إلى androidx.media3.session.MediaLibraryService والرمز باستخدام MediaBrowserCompat.MediaItem إلى androidx.media3.common.MediaItem.
  • MediaBrowserCompat (استنادًا إلى حِزم android.support.v4.media.* من androidx.media:media:1.4.3+)
    يمكنك نقل رمز العميل باستخدام MediaBrowserCompat أو MediaControllerCompat لاستخدام androidx.media3.session.MediaBrowser مع androidx.media3.common.MediaItem.

المتطلّبات الأساسية

  1. التأكّد من أنّ مشروعك يخضع للتحكّم في المصدر

    تأكَّد من إمكانية التراجع بسهولة عن التغييرات التي تم تطبيقها من خلال أدوات نقل البيانات المستندة إلى النصوص البرمجية. إذا لم يكن مشروعك خاضعًا للتحكم في المصدر حتى الآن، فهذا هو الوقت المناسب لبدء استخدامه. إذا كنت لا تريد القيام بذلك لسبب ما، فقم بعمل نسخة احتياطية من مشروعك قبل البدء في الترحيل.

  2. تحديث التطبيق

    • ننصحك بتحديث مشروعك لاستخدام أحدث إصدار من مكتبة ExoPlayer وإزالة أي طلبات بحث عن الطرق المتوقّفة نهائيًا. وإذا كنت تنوي استخدام النص البرمجي لإجراء عملية النقل، عليك مطابقة الإصدار الذي يتم تحديثه مع الإصدار الذي يعالجه النص البرمجي.

    • عليك زيادة إصدار compileSdkVersion من تطبيقك إلى 32 على الأقل.

    • ترقية Gradle ومكوّن Gradle الإضافي Android Studio إلى إصدار حديث يتوافق مع التبعيات المحدَّثة الواردة أعلاه. على سبيل المثال:

      • إصدار المكوّن الإضافي لنظام Gradle المتوافق مع Android: 7.1.0
      • إصدار Gradle: 7.4
    • استبدال كل عبارات استيراد حرف البدل التي تستخدم علامة نجمية (*) واستخدام عبارات استيراد مؤهلة بالكامل: احذف عبارات استيراد أحرف البدل واستخدِم Android Studio لاستيراد العبارات المؤهلة بالكامل (F2 - Alt/Enter، F2 - Alt/Enter، ...).

    • نقل البيانات من com.google.android.exoplayer2.PlayerView إلى com.google.android.exoplayer2.StyledPlayerView يعد ذلك ضروريًا لأنه لا يوجد ما يعادل com.google.android.exoplayer2.PlayerView في AndroidX Media3.

نقل بيانات ExoPlayer باستخدام ميزة "النص البرمجي"

يسهّل النص البرمجي الانتقال من com.google.android.exoplayer2 إلى الحزمة الجديدة وبنية الوحدة ضمن androidx.media3. يطبق النص البرمجي بعض عمليات التحقق من الصحة على مشروعك ويطبع التحذيرات في حالة فشل التحقق من الصحة. وبخلاف ذلك، يتم تطبيق تعيينات الفئات والحزم التي تمت إعادة تسميتها في موارد مشروع Gradle المتوافق مع Android المكتوب بلغة Java أو Kotlin.

usage: ./media3-migration.sh [-p|-c|-d|-v]|[-m|-l [-x <path>] [-f] PROJECT_ROOT]
 PROJECT_ROOT: path to your project root (location of 'gradlew')
 -p: list package mappings and then exit
 -c: list class mappings (precedence over package mappings) and then exit
 -d: list dependency mappings and then exit
 -l: list files that will be considered for rewrite and then exit
 -x: exclude the path from the list of file to be changed: 'app/src/test'
 -m: migrate packages, classes and dependencies to AndroidX Media3
 -f: force the action even when validation fails
 -v: print the exoplayer2/media3 version strings of this script
 -h, --help: show this help text

استخدام النص البرمجي للنقل

  1. نزِّل النص البرمجي لنقل البيانات من علامة مشروع ExoPlayer على GitHub المقابل للإصدار الذي حدّثت تطبيقك إليه:

    curl -o media3-migration.sh \
      "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
    
  2. جعل النص البرمجي قابلاً للتنفيذ:

    chmod 744 media3-migration.sh
    
  3. شغِّل النص البرمجي باستخدام --help للتعرّف على الخيارات.

  4. شغِّل النص البرمجي باستخدام -l لسرد مجموعة الملفات المحدَّدة لعملية نقل البيانات (استخدِم -f لفرض بطاقة البيانات بدون تحذيرات):

    ./media3-migration.sh -l -f /path/to/gradle/project/root
    
  5. شغِّل النص البرمجي باستخدام -m لتعيين الحزم والفئات والوحدات إلى Media3. سيؤدي تشغيل النص البرمجي مع الخيار -m إلى تطبيق التغييرات على الملفات المحدّدة.

    • التوقف عند حدوث خطأ في عملية التحقق من الصحة بدون إجراء تغييرات
    ./media3-migration.sh -m /path/to/gradle/project/root
    
    • فرض عملية التنفيذ

    وإذا وجد النص البرمجي مخالفة للمتطلبات الأساسية، يمكن فرض النقل باستخدام العلامة -f:

    ./media3-migration.sh -m -f /path/to/gradle/project/root
    
 # list files selected for migration when excluding paths
 ./media3-migration.sh -l -x "app/src/test/" -x "service/" /path/to/project/root
 # migrate the selected files
 ./media3-migration.sh -m -x "app/src/test/" -x "service/" /path/to/project/root

أكمِل هذه الخطوات اليدوية بعد تشغيل النص البرمجي باستخدام الخيار -m:

  1. التحقّق من كيفية تغيير النص البرمجي للرمز البرمجي: استخدِم أداة مختلفة وأصلِح المشاكل المحتملة (يمكنك تقديم خطأ إذا كنت تعتقد أنّ النص البرمجي يواجه مشكلة عامة حدثت بدون تمرير الخيار -f).
  2. إنشاء المشروع: يمكنك إمّا استخدام ./gradlew clean build أو في "استوديو Android" اختيار ملف > مزامنة المشروع مع ملفات Gradle، ثم إنشاء > حذف المشروع، ثم إنشاء > إعادة إنشاء المشروع (يمكنك تتبُّع التصميم في علامة التبويب "إنشاء - نتيجة الإصدار" في "استوديو Android".)

خطوات المتابعة المقترَحة:

  1. عليك حلّ الموافقة على الأخطاء المتعلّقة باستخدام واجهات برمجة التطبيقات غير الثابتة.
  2. استبدال طلبات البيانات من واجهة برمجة التطبيقات المتوقّفة نهائيًا: استخدِم واجهة برمجة التطبيقات البديلة المقترَحة. ضع مؤشّر الماوس فوق التحذير في "استوديو Android" وراجِع رمز JavaDoc للرمز الذي تم إيقافه لمعرفة ما يجب استخدامه بدلاً من استدعاء معيّن.
  3. ترتيب عبارات الاستيراد: افتح المشروع في "استوديو Android"، ثم انقر بزر الماوس الأيمن على عقدة مجلد الحزمة في عارض المشروع واختَر تحسين عمليات الاستيراد في الحِزم التي تحتوي على ملفات المصدر التي تم تغييرها.

استبدال MediaSessionConnector بـ androidx.media3.session.MediaSession

في عالم MediaSessionCompat القديم، كان MediaSessionConnector مسؤولًا عن مزامنة حالة المشغّل مع حالة الجلسة واستلام الأوامر من وحدات التحكم التي تتطلب تفويضًا لأساليب اللاعبين المناسبة. باستخدام AndroidX Media3، يتم إجراء ذلك من خلال MediaSession مباشرةً بدون الحاجة إلى موصِّل.

  1. إزالة كل المراجع واستخدام MediaSessionConnector: إذا استخدمت النص البرمجي المبرمَج لنقل فئات وحِزم ExoPlayer، من المحتمل أن يكون النص البرمجي قد ترك الرمز في حالة غير قابلة للتجميع بشأن MediaSessionConnector الذي لا يمكن حلّه. سيعرض لك "استوديو Android" التعليمات البرمجية المعطلة عند محاولة إنشاء تطبيق أو تشغيله.

  2. في ملف build.gradle الذي تحتفظ فيه بتبعياتك، أضِف تبعية للتنفيذ إلى وحدة جلسة AndroidX Media3 وأزِل التبعية القديمة:

    implementation "androidx.media3:media3-session:1.3.1"
    
  3. استبدِل MediaSessionCompat بـ androidx.media3.session.MediaSession.

  4. في الموقع الإلكتروني الخاص بالرموز البرمجية حيث أنشأت MediaSessionCompat القديمة، استخدِم androidx.media3.session.MediaSession.Builder من أجل إنشاء MediaSession. مرِّر المشغّل لإنشاء أداة إنشاء الجلسات.

    val player = ExoPlayer.Builder(context).build()
    mediaSession = MediaSession.Builder(context, player)
        .setSessionCallback(MySessionCallback())
        .build()
    
  5. نفِّذ MySessionCallback حسب ما يتطلبه تطبيقك، وهذا إجراء اختياري. إذا كنت تريد السماح لوحدات التحكّم بإضافة عناصر وسائط إلى المشغّل، عليك تنفيذ MediaSession.Callback.onAddMediaItems(). وهو يوفّر طرق واجهة برمجة تطبيقات مختلفة حالية وقديمة تضيف عناصر إلى المشغّل لتشغيلها بطريقة متوافقة مع الأنظمة القديمة. يشمل ذلك طرق MediaController.set/addMediaItems() لوحدة التحكّم في Media3، بالإضافة إلى طرق TransportControls.prepareFrom*/playFrom* لواجهة برمجة التطبيقات القديمة. يمكن العثور على نموذج لتنفيذ السمة onAddMediaItems في PlaybackService من التطبيق التجريبي للجلسة.

  6. حرر جلسة الوسائط في موقع التعليمة البرمجية حيث دمّرت جلستك قبل عملية الترحيل:

    mediaSession?.run {
      player.release()
      release()
      mediaSession = null
    }
    

وظيفة MediaSessionConnector في Media3

يعرض الجدول التالي واجهات برمجة تطبيقات Media3 التي تعالج وظائف تم تنفيذها سابقًا في MediaSessionConnector.

MediaSessionConnectorAndroidX Media3
CustomActionProvider MediaSession.Callback.onCustomCommand()/ MediaSession.setCustomLayout()
PlaybackPreparer MediaSession.Callback.onAddMediaItems() (تتم تسمية prepare() داخليًا)
QueueNavigator ForwardingPlayer
QueueEditor MediaSession.Callback.onAddMediaItems()
RatingCallback MediaSession.Callback.onSetRating()
PlayerNotificationManager DefaultMediaNotificationProvider/ MediaNotification.Provider

نقل بيانات MediaBrowserService إلى MediaLibraryService

قدّم نظام التشغيل AndroidX Media3 واجهة برمجة تطبيقات MediaLibraryService بدلاً من MediaBrowserServiceCompat. تقدم JavaDoc لـ MediaLibraryService وفئتها الفاخرة MediaSessionService مقدمة جيدة عن واجهة برمجة التطبيقات ونموذج البرمجة غير المتزامن للخدمة.

تتوافق MediaLibraryService مع التصاميم MediaBrowserService القديمة. يظل تطبيق العميل الذي يستخدم MediaBrowserCompat أو MediaControllerCompat يعمل بدون تغيير الرمز عند الاتصال بـ MediaLibraryService. بالنسبة إلى العميل، يحدّد ما إذا كان تطبيقك يستخدم MediaLibraryService أو MediaBrowserServiceCompat قديمة.

رسم تخطيطي لمكوّنات التطبيق يعرض الخدمة والنشاط والتطبيقات الخارجية
الشكل 1: نظرة عامة على مكوّنات تطبيق الوسائط
  1. لكي يعمل التوافق مع الأنظمة القديمة، عليك تسجيل واجهتَي الخدمة من خلال خدمتك في AndroidManifest.xml. بهذه الطريقة، يعثر العميل على خدمتك من خلال واجهة الخدمة المطلوبة:

    <service android:name=".MusicService" android:exported="true">
        <intent-filter>
            <action android:name="androidx.media3.session.MediaLibraryService"/>
            <action android:name="android.media.browse.MediaBrowserService" />
        </intent-filter>
    </service>
    
  2. في ملف build.gradle الذي تحتفظ فيه بتبعياتك، أضِف تبعية للتنفيذ إلى وحدة جلسة AndroidX Media3 وأزِل التبعية القديمة:

    implementation "androidx.media3:media3-session:1.3.1"
    
  3. تغيير خدمتك لتكتسب من MediaLibraryService بدلاً من MediaBrowserService كما ذكرنا سابقًا، تتوافق خدمة MediaLibraryService مع الإصدار القديم MediaBrowserService. ووفقًا لذلك، لا تزال واجهة برمجة التطبيقات الأوسع التي تقدمها الخدمة للعملاء كما هي. لذا، من المرجّح أن يحتفظ التطبيق بمعظم المنطق المطلوب لتنفيذ MediaBrowserService وتكييفه مع MediaLibraryService الجديد.

    في ما يلي الاختلافات الرئيسية مقارنةً بإصدار MediaBrowserServiceCompat القديم:

    • تنفيذ طُرق دورة حياة الخدمة: الطرق التي يجب إلغاءها على الخدمة نفسها هي onCreate/onDestroy، حيث يخصّص/يخصص التطبيق جلسة المكتبة والمشغّل والموارد الأخرى. بالإضافة إلى الطُرق العادية لدورة حياة الخدمة، يحتاج التطبيق إلى إلغاء السمة onGetSession(MediaSession.ControllerInfo) لعرض عنصر MediaLibrarySession الذي تم إنشاؤه في onCreate.

    • تنفيذ MediaLibraryService.MediaLibrarySessionCallback: يتطلب إنشاء جلسة MediaLibraryService.MediaLibrarySessionCallback تنفيذ أساليب واجهة برمجة التطبيقات للنطاق الفعلية. لذا بدلاً من إلغاء طرق واجهة برمجة التطبيقات للخدمة القديمة، سيتم إلغاء طرق MediaLibrarySession.Callback بدلاً من ذلك.

      يتم بعد ذلك استخدام معاودة الاتصال لإنشاء MediaLibrarySession:

      mediaLibrarySession =
            MediaLibrarySession.Builder(this, player, MySessionCallback())
               .build()
      

      يمكنك البحث عن واجهة برمجة التطبيقات الكاملة لـ MediaLibrarySessionCallback في وثائق واجهة برمجة التطبيقات.

    • التنفيذ MediaSession.Callback.onAddMediaItems(): يعرض معاودة الاتصال onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>) طرقًا مختلفة حالية وقديمة لواجهة برمجة التطبيقات تضيف عناصر إلى المشغّل لتشغيلها بطريقة متوافقة مع الأنظمة القديمة. يشمل ذلك طرق MediaController.set/addMediaItems() لوحدة التحكّم في Media3، بالإضافة إلى طرق TransportControls.prepareFrom*/playFrom* لواجهة برمجة التطبيقات القديمة. يمكن العثور على نموذج لتنفيذ معاودة الاتصال في PlaybackService من تطبيق العرض التوضيحي للجلسة.

    • يستخدم نظام AndroidX Media3 androidx.media3.common.MediaItem بدلاً من MediaBrowserCompat.MediaItem وMediaMetadataCompat. يجب تغيير أجزاء من الرمز المرتبط بالفئات القديمة وفقًا لذلك أو ربطها بسياسة MediaItem Media3 بدلاً من ذلك.

    • تم تغيير نموذج البرمجة غير المتزامن إلى Futures العام على عكس أسلوب Result القابل للفصل في MediaBrowserServiceCompat. يمكن أن يعرض تنفيذ الخدمة ListenableFuture غير متزامن بدلاً من فصل نتيجة أو عرض مستقبل فوري لعرض قيمة مباشرةً.

إزالة PlayerNotificationManager

يتيح MediaLibraryService تلقّي إشعارات الوسائط تلقائيًا، ويمكن إزالة PlayerNotificationManager عند استخدام MediaLibraryService أو MediaSessionService.

يمكن لأي تطبيق تخصيص الإشعار عن طريق ضبط سمة MediaNotification.Provider مخصّصة في onCreate() لتحلّ محل DefaultMediaNotificationProvider. بعد ذلك، يتولى MediaLibraryService بدء الخدمة في المقدّمة على النحو المطلوب.

عند إلغاء MediaLibraryService.updateNotification()، يمكن للتطبيق الحصول على الملكية الكاملة لنشر إشعار وبدء/إيقاف الخدمة في المقدّمة على النحو المطلوب.

نقل رمز العميل باستخدام MediaBrowser

باستخدام AndroidX Media3، تنفّذ MediaBrowser الواجهات MediaController/Player ويمكن استخدامها للتحكم في تشغيل الوسائط إلى جانب تصفح مكتبة الوسائط. إذا كان عليك إنشاء MediaBrowserCompat وMediaControllerCompat في العالم القديم، يمكنك استخدام MediaBrowser فقط في Media3.

يمكن إنشاء MediaBrowser في انتظار الاتصال بالخدمة التي يتم إنشاؤها:

scope.launch {
    val sessionToken =
        SessionToken(context, ComponentName(context, MusicService::class.java)
    browser =
        MediaBrowser.Builder(context, sessionToken))
            .setListener(BrowserListener())
            .buildAsync()
            .await()
    // Get the library root to start browsing the library.
    root = browser.getLibraryRoot(/* params= */ null).await();
    // Add a MediaController.Listener to listen to player state events.
    browser.addListener(playerListener)
    playerView.setPlayer(browser)
}

ألقِ نظرة على مقالة التحكّم في التشغيل في جلسة تشغيل الوسائط للتعرّف على كيفية إنشاء MediaController للتحكم في التشغيل في الخلفية.

مزيد من الخطوات وإخلاء مساحة

أخطاء غير مستقرة في واجهة برمجة التطبيقات

بعد الانتقال إلى Media3، قد تظهر لك أخطاء غير مرغوب فيها بشأن الاستخدامات غير الثابتة لواجهة برمجة التطبيقات. إنّ واجهات برمجة التطبيقات هذه آمنة للاستخدام، وتمثّل أخطاء الوبر منتج ثانوي ضمن ضمانات التوافق الثنائي الجديدة. إذا لم يكن لديك توافق ثنائي صارم، يمكن منع هذه الأخطاء بأمان باستخدام التعليق التوضيحي @OptIn.

خلفية

لم يقدّم أي من الإصدار 1 أو الإصدار 2 من ExoPlayer ضمانات صارمة بشأن التوافق الثنائي للمكتبة بين الإصدارات اللاحقة. يتّسم سطح واجهة برمجة تطبيقات ExoPlayer بأنّه كبير جدًا من حيث التصميم، ما يتيح للتطبيقات تخصيص كل جانب من جوانب التشغيل تقريبًا. قد تتضمن الإصدارات اللاحقة من ExoPlayer أحيانًا عمليات إعادة تسمية للرموز أو تغييرات قد تؤدي إلى أعطال أخرى (مثل إضافة طرق جديدة مطلوبة على الواجهات). في معظم الحالات، تم الحدّ من هذه الأعطال من خلال تقديم الرمز الجديد إلى جانب إيقاف الرمز القديم لبعض الإصدارات، ما يمنح المطوّرين وقتًا لنقل بيانات استخدامهم، لكن هذا لم يكن ممكنًا دائمًا.

وأدّت هذه التغييرات التي قد تؤدي إلى تعطُّل إلى حدوث مشكلتين لمستخدمي الإصدارَين 1 و2 من ExoPlayer:

  1. قد تؤدي الترقية من إصدار ExoPlayer إلى إيقاف تجميع الرموز البرمجية.
  2. إذا كان التطبيق الذي كان يعتمد على ExoPlayer بشكل مباشر أو من خلال مكتبة وسيطة، كان يجب أن يضمن أن كلتا التبعية كانتا من نفس الإصدار، وإلا فقد تؤدي حالات عدم التوافق الثنائي إلى أعطال في وقت التشغيل.

التحسينات في Media3

تضمن Media3 التوافق الثنائي لمجموعة فرعية من مساحة عرض واجهة برمجة التطبيقات. يتم تمييز الأجزاء التي لا تضمن التوافق الثنائي باستخدام @UnstableApi. لتوضيح هذا التمييز، ينشأ عن استخدام رموز واجهة برمجة التطبيقات غير المستقرة خطأ غير مرغوب فيه ما لم تتم إضافة تعليقات توضيحية إليه باستخدام @OptIn.

بعد نقل البيانات من الإصدار الثاني ExoPlayer إلى Media3، قد يظهر لك الكثير من الأخطاء غير الثابتة في واجهة برمجة التطبيقات. قد يجعل هذا الأمر يبدو وكأن Media3 "أقل ثباتًا" من الإصدار 2 من ExoPlayer. ولكن الأمر ليس كذلك. تتمتع الأجزاء "غير الثابتة" من واجهة برمجة التطبيقات Media3 API بالمستوى نفسه من الثبات مثل كامل سطح واجهة برمجة التطبيقات ExoPlayer v2، ولا تتوفر ضمانات السطح الثابت لـ Media3 API في الإصدار 2 من ExoPlayer على الإطلاق. الفرق هو ببساطة أن خطأ الوبر ينبهك الآن إلى المستويات المختلفة للثبات.

معالجة أخطاء البرامج غير الثابتة في واجهة برمجة التطبيقات

لديك خياران لمعالجة أخطاء البرامج غير الثابتة لواجهة برمجة التطبيقات:

  • يمكنك التبديل إلى استخدام واجهة برمجة تطبيقات مستقرة تحقق النتيجة نفسها.
  • يمكنك مواصلة استخدام واجهة برمجة التطبيقات غير الثابتة وإضافة تعليقات توضيحية إلى الاستخدام باستخدام @OptIn.

    import androidx.annotation.OptIn
    import androidx.media3.common.util.UnstableApi
    
    @OptIn(UnstableApi::class)
    fun functionUsingUnstableApi() {
      // Do something useful.
    }
    

    يُرجى العِلم أنّ هناك أيضًا تعليق توضيحي kotlin.OptIn يجب عدم استخدامه. من المهم الالتزام بالتعليق التوضيحي androidx.annotation.OptIn لهذا الغرض.

    لقطة شاشة: كيفية إضافة التعليق التوضيحي الخاص بالموافقة
    الشكل 2: إضافة تعليق توضيحي باستخدام @androidx.annotations.OptIn باستخدام "استوديو Android".

يمكن تفعيل كلّ الحِزم من خلال إضافة package-info.java:

@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;

import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;

يمكن الموافقة على المشاريع بأكملها من خلال منع خطأ الوبر المحدد في ملف lint.xml الخاص بها. راجِع JavaDoc للتعليق التوضيحي UnstableApi للحصول على مزيد من التفاصيل.

واجهات برمجة التطبيقات التي تم إيقافها نهائيًا

قد تلاحظ أنّ طلبات البيانات من واجهات برمجة التطبيقات المتوقّفة تظهر في "استوديو Android". ونحن ننصح باستبدال هذه الطلبات بالبديل المناسب. مرِّر مؤشر الماوس فوق الرمز لعرض مستند JavaDoc الذي يحدِّد واجهة برمجة التطبيقات التي يجب استخدامها بدلاً من ذلك.

لقطة شاشة: كيفية عرض JavaDoc باستخدام بديل الطريقة المتوقّفة
الشكل 3: يقترح تلميح JavaDoc في "استوديو Android" بديلاً لأي رمز تم إيقافه.

عيّنات التعليمات البرمجية والتطبيقات التجريبية

  • تطبيق العرض التوضيحي لجلسة AndroidX Media3 (للأجهزة الجوّالة وWearOS)
    • الإجراءات المخصّصة
    • إشعار واجهة مستخدم النظام، MediaButton/BT
    • التحكّم في تشغيل "مساعد Google"
  • UAMP: Android Media Player (branch media3) (الأجهزة الجوّالة و AutomotiveOS)
    • إشعار واجهة مستخدم النظام، MediaButton/BT، استئناف التشغيل
    • التحكّم في تشغيل الأجهزة من خلال "مساعد Google" أو WearOS
    • AutomotiveOS: طلب مخصّص وتسجيل الدخول