يجب نقل التطبيقات التي تستخدم حاليًا المكتبة المستقلة 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
. - متوافقة مع الإصدارات القديمة من واجهات برمجة التطبيقات الخاصة بالعملاء في Media-compat
(
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 (حسب حِزم
androidx.media:media:1.4.3+
)
يمكنك نقل رمز العميل باستخدامMediaBrowserCompat
أوMediaControllerCompat
لاستخدامandroidx.media3.session.MediaBrowser
معandroidx.media3.common.MediaItem
.android.support.v4.media.*
المتطلّبات الأساسية
التأكّد من أنّ مشروعك يخضع للتحكّم في المصدر
تأكَّد من إمكانية التراجع بسهولة عن التغييرات التي تطبّقها أدوات نقل البيانات المستندة إلى نصوص برمجية. إذا لم يكن مشروعك خاضعًا للتحكّم في المصدر بعد، هذا هو الوقت المناسب للبدء. إذا كنت لا تريد إجراء ذلك لسبب ما، عليك إنشاء نسخة احتياطية من مشروعك قبل بدء عملية نقل البيانات.
تحديث تطبيقك
ننصحك بتحديث مشروعك لاستخدام أحدث إصدار من مكتبة ExoPlayer وإزالة أي استدعاءات للطُرق المتوقّفة نهائيًا. إذا كنت تنوي استخدام النص البرمجي لإجراء عملية النقل، عليك التأكّد من أنّ الإصدار الذي تريد التحديث إليه يتطابق مع الإصدار الذي يتعامل معه النص البرمجي.
زيادة قيمة compileSdkVersion لتطبيقك إلى 32 على الأقل
ترقية Gradle والمكوّن الإضافي لنظام Gradle المتوافق مع Android في "استوديو Android" إلى إصدار حديث متوافق مع التبعيات المعدَّلة المذكورة أعلاه على سبيل المثال:
- إصدار المكوّن الإضافي لنظام 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
. يطبّق النص البرمجي بعض عمليات التحقّق من الصحة على مشروعك ويعرض تحذيرات في حال فشل عملية التحقّق.
بخلاف ذلك، يتم تطبيق عمليات تحديد الهوية الخاصة بالفئات والحِزم التي تمت إعادة تسميتها في موارد مشروع 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
استخدام النص البرمجي لنقل البيانات
نزِّل نص النقل البرمجي من علامة مشروع ExoPlayer على GitHub التي تتوافق مع الإصدار الذي تم تحديث تطبيقك إليه:
curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
اجعل النص البرمجي قابلاً للتنفيذ:
chmod 744 media3-migration.sh
نفِّذ النص البرمجي باستخدام
--help
للتعرّف على الخيارات.نفِّذ النص البرمجي باستخدام
-l
لإدراج مجموعة الملفات التي تم اختيارها لنقل البيانات (استخدِم-f
لفرض الإدراج بدون تحذيرات):./media3-migration.sh -l -f /path/to/gradle/project/root
نفِّذ النص البرمجي باستخدام
-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
:
- التحقّق من طريقة تغيير النص البرمجي لرمزك: استخدِم أداة مقارنة وأصلِح المشاكل المحتملة (ننصحك بإرسال تقرير عن خطأ إذا كنت تعتقد أنّ النص البرمجي يتضمّن مشكلة عامة تم إدخالها بدون تمرير الخيار
-f
). - إنشاء المشروع: يمكنك استخدام
./gradlew clean build
أو الانتقال في "استوديو Android" إلى ملف > مزامنة المشروع مع ملفات Gradle، ثم إنشاء > تنظيف المشروع، ثم إنشاء > إعادة إنشاء المشروع (يمكنك تتبُّع عملية الإنشاء في علامة التبويب "إنشاء - ناتج الإنشاء" في "استوديو Android").
خطوات المتابعة المقترَحة:
- حلّ مشكلة الموافقة على تلقّي أخطاء بشأن استخدام واجهات برمجة تطبيقات غير مستقرة
- استبدال طلبات البيانات من واجهة برمجة التطبيقات التي تم إيقافها نهائيًا: استخدِم واجهة برمجة التطبيقات البديلة المقترَحة. مرِّر المؤشر فوق التحذير في "استوديو Android"، واطّلِع على JavaDoc للرمز المتوقّف نهائيًا لمعرفة ما يجب استخدامه بدلاً من عملية استدعاء معيّنة.
- ترتيب عبارات الاستيراد: افتح المشروع في "استوديو Android"، ثم انقر بزر الماوس الأيمن على عقدة مجلد حزمة في عارض المشروع واختَر تحسين عمليات الاستيراد في الحِزم التي تحتوي على ملفات المصدر التي تم تغييرها.
استبدال MediaSessionConnector
بـ androidx.media3.session.MediaSession
في الإصدار القديم من MediaSessionCompat
، كان MediaSessionConnector
مسؤولاً عن مزامنة حالة المشغّل مع حالة الجلسة وتلقّي الأوامر من وحدات التحكّم التي تحتاج إلى تفويض إلى طرق المشغّل المناسبة. باستخدام AndroidX Media3، يتم ذلك من خلال MediaSession
مباشرةً
بدون الحاجة إلى موصّل.
إزالة جميع الإشارات إلى MediaSessionConnector واستخدامه: إذا كنت قد استخدمت النص البرمجي الآلي لنقل بيانات فئات وحِزم ExoPlayer، من المحتمل أنّ النص البرمجي قد ترك الرمز في حالة غير قابلة للتجميع فيما يتعلق بـ
MediaSessionConnector
التي لا يمكن حلّها. سيُظهر لك Android Studio الرمز البرمجي المعطّل عند محاولة إنشاء التطبيق أو تشغيله.في ملف
build.gradle
الذي تحتفظ فيه بملفات التبعية، أضِف ملف تبعية للتنفيذ إلى وحدة جلسة Media3 في AndroidX وأزِل ملف التبعية القديم:implementation "androidx.media3:media3-session:1.7.1"
استبدِل
MediaSessionCompat
بـandroidx.media3.session.MediaSession
.في الموقع الإلكتروني الذي أنشأت فيه
MediaSessionCompat
القديم، استخدِمandroidx.media3.session.MediaSession.Builder
من أجل إنشاءMediaSession
. مرِّر عنصر المشغّل لإنشاء أداة إنشاء الجلسة.val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(MySessionCallback()) .build()
نفِّذ
MySessionCallback
على النحو المطلوب في تطبيقك. هذه الخطوة اختيارية. إذا أردت السماح لأدوات التحكّم بإضافة عناصر وسائط إلى المشغّل، عليك تنفيذMediaSession.Callback.onAddMediaItems()
. توفّر هذه الفئة طرقًا مختلفة لواجهة برمجة التطبيقات الحالية والقديمة، وتتيح إضافة عناصر وسائط إلى المشغّل لتشغيلها بطريقة متوافقة مع الإصدارات القديمة. ويشمل ذلك طرقMediaController.set/addMediaItems()
الخاصة بوحدة التحكّم Media3، بالإضافة إلى طرقTransportControls.prepareFrom*/playFrom*
الخاصة بواجهة برمجة التطبيقات القديمة. يمكن العثور على نموذج لتنفيذonAddMediaItems
فيPlaybackService
لتطبيق العرض التوضيحي للجلسة.أصدر جلسة الوسائط في الموقع الإلكتروني الذي تم فيه تدمير الجلسة قبل نقل البيانات:
mediaSession?.run { player.release() release() mediaSession = null }
وظائف MediaSessionConnector
في Media3
يوضِّح الجدول التالي واجهات برمجة تطبيقات Media3 التي تتعامل مع الوظائف التي تم تنفيذها سابقًا في MediaSessionConnector
.
MediaSessionConnector | AndroidX Media3 |
---|---|
CustomActionProvider |
MediaSession.Callback.onCustomCommand()/
MediaSession.setMediaButtonPreferences() |
PlaybackPreparer |
MediaSession.Callback.onAddMediaItems()
(يتم استدعاء prepare() داخليًا)
|
QueueNavigator |
ForwardingSimpleBasePlayer |
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
قديمًا.

لكي تعمل إمكانية التوافق مع الإصدارات السابقة، عليك تسجيل كلتا واجهتَي الخدمة مع خدمتك في
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>
في ملف
build.gradle
الذي تحتفظ فيه بملفات التبعيات، أضِف إحدى التبعيات الخاصة بالتنفيذ إلى وحدة جلسة Media3 في AndroidX وأزِل التبعية القديمة:implementation "androidx.media3:media3-session:1.7.1"
تغيير خدمتك لتستند إلى
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
لتطبيق العرض التوضيحي للجلسة.تستخدم مكتبة Media3 في AndroidX
androidx.media3.common.MediaItem
بدلاً من MediaBrowserCompat.MediaItem وMediaMetadataCompat. يجب تغيير أجزاء الرمز المرتبط بالفئات القديمة وفقًا لذلك أو ربطها بـ Media3MediaItem
بدلاً من ذلك.تم تغيير نموذج البرمجة غير المتزامنة العام إلى
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 بشأن استخدامات واجهة برمجة التطبيقات غير الثابتة.
يمكن استخدام واجهات برمجة التطبيقات هذه بأمان، والأخطاء التي تظهر في أداة Lint هي نتيجة ثانوية لضمانات التوافق الثنائي الجديدة. إذا لم تكن بحاجة إلى توافق صارم مع تنسيق ثنائي، يمكن تجاهل هذه الأخطاء بأمان باستخدام التعليق التوضيحي @OptIn
.
الخلفية
لم يقدّم الإصداران 1 و2 من ExoPlayer ضمانات صارمة بشأن توافق البرنامج الثنائي للمكتبة بين الإصدارات اللاحقة. تم تصميم مساحة ExoPlayer API لتكون كبيرة جدًا، وذلك للسماح للتطبيقات بتخصيص كل جانب تقريبًا من جوانب التشغيل. في الإصدارات اللاحقة من ExoPlayer، تم في بعض الأحيان إعادة تسمية الرموز أو إجراء تغييرات أخرى غير متوافقة (مثل طرق جديدة مطلوبة في الواجهات). في معظم الحالات، تم التخفيف من حدة هذه المشاكل من خلال طرح الرمز الجديد إلى جانب إيقاف الرمز القديم نهائيًا لعدة إصدارات، وذلك لإتاحة الوقت للمطوّرين لنقل استخداماتهم، ولكن لم يكن ذلك ممكنًا دائمًا.
أدّت هذه التغييرات غير المتوافقة إلى حدوث مشكلتين لمستخدمي مكتبتَي ExoPlayer v1 وv2:
- قد تؤدي الترقية من إصدار ExoPlayer إلى توقّف تجميع الرمز.
- كان على التطبيق الذي يعتمد على ExoPlayer بشكل مباشر وعبر مكتبة وسيطة أن يضمن أنّ كلا التبعيتَين هما الإصدار نفسه، وإلا قد تؤدي حالات عدم التوافق الثنائي إلى حدوث أعطال أثناء التشغيل.
تحسينات في Media3
تضمن Media3 توافق الرمز الثنائي مع مجموعة فرعية من مساحة واجهة برمجة التطبيقات. تم وضع العلامة
@UnstableApi
على الأجزاء التي لا تضمن التوافق الثنائي. ولتوضيح هذا الفرق، تؤدي استخدامات رموز واجهة برمجة التطبيقات غير الثابتة إلى حدوث خطأ في أداة Lint ما لم يتم إضافة التعليق التوضيحي @OptIn
إليها.
بعد نقل البيانات من ExoPlayer الإصدار 2 إلى Media3، قد تظهر لك الكثير من أخطاء lint غير الثابتة في واجهة برمجة التطبيقات . وقد يبدو ذلك وكأنّ Media3 "أقل ثباتًا" من الإصدار 2 من ExoPlayer. ولكن ليست هذه هي القضية. تتضمّن الأجزاء "غير الثابتة" من Media3 API مستوى الثبات نفسه الذي تتضمّنه واجهة برمجة التطبيقات الكاملة في ExoPlayer الإصدار 2، ولا تتوفّر ضمانات واجهة برمجة التطبيقات الثابتة في Media3 في ExoPlayer الإصدار 2 على الإطلاق. والفرق الوحيد هو أنّ خطأ Lint ينبّهك الآن إلى مستويات الثبات المختلفة.
التعامل مع أخطاء lint غير الثابتة في واجهة برمجة التطبيقات
راجِع قسم تحديد المشاكل وحلّها بشأن أخطاء Lint هذه للحصول على تفاصيل حول كيفية إضافة التعليقات التوضيحية @OptIn
إلى استخدامات Java وKotlin لواجهات برمجة التطبيقات غير الثابتة.
واجهات برمجة التطبيقات المتوقّفة نهائيًا
قد تلاحظ أنّ طلبات البيانات من واجهات برمجة التطبيقات المتوقّفة نهائيًا يتم وضع خط في منتصفها في "استوديو Android". ننصحك باستبدال هذه المكالمات بالبديل المناسب. مرِّر مؤشر الماوس فوق الرمز للاطّلاع على JavaDoc الذي يوضّح واجهة برمجة التطبيقات التي يجب استخدامها بدلاً من ذلك.

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