دليل نقل البيانات إلى 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 والمكوّن الإضافي "Android Studio Gradle" إلى إصدار حديث يعمل مع الملحقات المُعدَّلة الواردة أعلاه. على سبيل المثال:

      • إصدار المكوّن الإضافي لنظام Gradle المتوافق مع Android: 7.1.0
      • إصدار Gradle: 7.4
    • استبدال جميع عبارات استيراد أحرف البدل التي تستخدم علامة النجمة (*) واستخدام عبارات الاستيراد المؤهلة بالكامل: احذف عبارات استيراد أحرف البدل واستخدِم "استوديو Android" لاستيراد العبارات المؤهلة بالكامل (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. يطبّق النص البرمجي بعض عمليات التحقّق من الصحة على مشروعك ويطبع تحذيرات في حال تعذّر إكمال عملية التحقّق. وبخلاف ذلك، يطبّق عمليات الربط للفئات والحِزم التي تمت إعادة تسميتها في موارد مشروع Android gradle المكتوب بلغة 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 Studio، واطّلِع على JavaDoc للرمز المتوقّف نهائيًا لمعرفة ما يجب استخدامه بدلاً من طلب معيّن.
  3. ترتيب عبارات الاستيراد: افتح المشروع في "استوديو Android"، ثم انقر بزر الماوس الأيمن على عقدة مجلد الحزمة في عارض المشروع واختَر تحسين عمليات الاستيراد في الحزم التي تحتوي على الملفات المصدر التي تمّ تغييرها.

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

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

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

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

    implementation "androidx.media3:media3-session:1.4.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. لكي تعمل التوافقية مع الإصدارات القديمة، عليك تسجيل كل من منصتي IDE مع خدمتك في 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.4.1"
    
  3. غيِّر خدمتك لترث من MediaLibraryService بدلاً من MediaBrowserService كما ذكرنا سابقًا، يتوافق MediaLibraryService مع الإصدار القديم MediaBrowserService. وبناءً على ذلك، تظل واجهة برمجة التطبيقات الأوسع نطاقًا التي تقدّمها الخدمة للعملاء كما هي. لذا من المحتمل أن يستطيع أي تطبيق الاحتفاظ بمعظم منطق تنفيذ MediaBrowserService وتعديله بما يتناسب مع MediaLibraryService الجديد.

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

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

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

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

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

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

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

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

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

إزالة 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، قد تظهر لك أخطاء أداة Lint حول الاستخدامات غير المستقرة لواجهة برمجة التطبيقات. إن واجهات برمجة التطبيقات هذه آمنة للاستخدام، كما أن أخطاء الوبر هي منتج ثانوي لضمانات التوافق الثنائي الجديدة. إذا لم تكن بحاجة إلى توافق ثنائي صارم، يمكن إخفاء هذه الأخطاء بأمان باستخدام @OptIn تعليق توضيحي.

خلفية

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

أدّت هذه التغييرات الأساسية إلى حدوث مشكلتَين لمستخدمي مكتبتَي ExoPlayer v1 وv2:

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

تحسينات في Media3

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

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

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

راجِع قسم تحديد المشاكل وحلّها في أخطاء أداة Lint هذه للاطّلاع على تفاصيل حول كيفية إضافة تعليقات توضيحية إلى استخدامات Java وKotlin لواجهات برمجة التطبيقات غير المستقرة باستخدام @OptIn.

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

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

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

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

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