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

      • إصدار المكوّن الإضافي لنظام Gradle المتوافق مع Android: 7.1.0
      • إصدار Gradle: 7.4
    • استبدِل كل عبارات الاستيراد التي تستخدم العلامة النجمية (*) واستخدِم عبارات الاستيراد المؤهَّلة بالكامل: احذف عبارات استخدام العلامة النجمية لاستيراد عبارات استخدام العلامة النجمية بالكامل (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(). ويقدّم هذا الإصدار طرقًا مختلفة حالية و قديمة لواجهة برمجة التطبيقات تضيف عناصر وسائط إلى المشغّل لتشغيلها بطريقة متوافقة مع الإصدارات القديمة. ويشمل ذلك methods MediaController.set/addMediaItems() لوحدة التحكّم في Media3، بالإضافة إلى methodsTransportControls.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، قد تظهر لك أخطاء فحص الأخطاء المتعلقة باستخدامات واجهة برمجة التطبيقات غير المستقرة. إنّ واجهات برمجة التطبيقات هذه آمنة للاستخدام، وتعدّ أخطاء التدقيق ثانوية في إطار ضمانات التوافق الجديدة للملفات الثنائية. إذا لم تكن بحاجة إلى توافق ثنائي صارم، يمكن إخفاء هذه الأخطاء بأمان باستخدام @OptIn تعليق توضيحي.

خلفية

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

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

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

تحسينات في Media3

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

بعد نقل البيانات من الإصدار 2 من ExoPlayer إلى Media3، قد تظهر لك الكثير من أخطاء فحص أخطاء API غير المستقرة. قد يؤدي ذلك إلى ظهور 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: الأوامر المخصّصة وتسجيل الدخول