برنامههایی که در حال حاضر از کتابخانه مستقل com.google.android.exoplayer2 و androidx.media استفاده میکنند، باید به androidx.media3 مهاجرت کنند. از اسکریپت مهاجرت برای انتقال فایلهای ساخت gradle، فایلهای منبع جاوا و کاتلین و فایلهای طرحبندی XML از ExoPlayer 2.19.1 به AndroidX Media3 1.1.1 استفاده کنید.
نمای کلی
قبل از مهاجرت، بخشهای زیر را مرور کنید تا در مورد مزایای APIهای جدید، APIهای مورد نیاز برای مهاجرت و پیشنیازهایی که پروژه برنامه شما باید داشته باشد، بیشتر بدانید.
چرا به Jetpack Media3 مهاجرت کنیم؟
- این خانه جدید ExoPlayer است، در حالی که
com.google.android.exoplayer2دیگر پشتیبانی نمیشود. - با استفاده از
MediaBrowser/MediaControllerبه رابط برنامهنویسی کاربردی پخشکننده (Player API) از طریق کامپوننتها/فرآیندها دسترسی پیدا کنید. - از قابلیتهای توسعهیافتهی
MediaSessionوMediaControllerAPI استفاده کنید. - قابلیتهای پخش را با کنترل دسترسی دقیق تبلیغ کنید.
- با حذف
MediaSessionConnectorوPlayerNotificationManagerبرنامه خود را ساده کنید . - سازگار با APIهای کلاینت سازگار با رسانه (
MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)
APIهای رسانهای برای مهاجرت به 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منتقل کنید.
پیشنیازها
مطمئن شوید که پروژه شما تحت کنترل منبع است
مطمئن شوید که میتوانید به راحتی تغییرات اعمال شده توسط ابزارهای مهاجرت اسکریپتشده را به حالت اولیه برگردانید. اگر هنوز پروژه خود را تحت کنترل منبع ندارید، اکنون زمان مناسبی برای شروع آن است. اگر به هر دلیلی نمیخواهید این کار را انجام دهید، قبل از شروع مهاجرت، یک نسخه پشتیبان از پروژه خود تهیه کنید.
برنامه خود را بهروزرسانی کنید
توصیه میکنیم پروژه خود را بهروزرسانی کنید تا از جدیدترین نسخه کتابخانه ExoPlayer استفاده کند و هرگونه فراخوانی به متدهای منسوخشده را حذف کنید. اگر قصد دارید از اسکریپت برای مهاجرت استفاده کنید ، باید نسخهای را که به آن بهروزرسانی میکنید با نسخهای که توسط اسکریپت مدیریت میشود، مطابقت دهید.
compileSdkVersion برنامه خود را حداقل به ۳۲ افزایش دهید.
Gradle و افزونهی Gradle اندروید استودیو را به آخرین نسخهای که با وابستگیهای بهروزرسانیشدهی بالا کار میکند، ارتقا دهید . برای مثال:
- نسخه افزونه اندروید Gradle: 7.1.0
- نسخه گرادل: ۷.۴
تمام عبارات ورودی wildcard که از علامت ستاره (*) استفاده میکنند را جایگزین کنید و از عبارات ورودی کامل استفاده کنید: عبارات ورودی wildcard را حذف کنید و از اندروید استودیو برای وارد کردن عبارات کامل (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 اندروید که به زبان جاوا یا کاتلین نوشته شده است، اعمال میکند.
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 این مراحل دستی را انجام دهید:
- بررسی کنید که اسکریپت چگونه کد شما را تغییر داده است : از یک ابزار diff استفاده کنید و مشکلات احتمالی را برطرف کنید (اگر فکر میکنید اسکریپت یک مشکل کلی دارد که بدون عبور از گزینه
-fایجاد شده است، ثبت یک اشکال را در نظر بگیرید). - پروژه را بسازید : یا از
./gradlew clean build استفاده کنید یا در اندروید استودیو مسیر File > Sync Project with Gradle Files را انتخاب کنید، سپس Build > Clean project و در نهایت Build > Rebuild project را انتخاب کنید (ساخت خود را در تب 'Build - Build Output' در اندروید استودیو مانیتور کنید).
مراحل پیگیری توصیه شده:
- Resolve opt-in for errors regarding usage of unstable APIs .
- جایگزینی فراخوانیهای API منسوخشده : از API جایگزین پیشنهادی استفاده کنید. در اندروید استودیو، نشانگر ماوس را روی هشدار نگه دارید و برای یافتن اینکه به جای فراخوانی مشخصشده از چه چیزی استفاده کنید، به JavaDoc نماد منسوخشده مراجعه کنید.
- مرتبسازی دستورات ایمپورت : پروژه را در اندروید استودیو باز کنید، سپس روی گره پوشه پکیج در نمایشگر پروژه کلیک راست کرده و روی پکیجهایی که حاوی فایلهای منبع تغییر یافته هستند، گزینه Optimize import را انتخاب کنید.
MediaSessionConnector را با androidx.media3.session.MediaSession جایگزین کنید
در دنیای قدیمی MediaSessionCompat ، MediaSessionConnector مسئول همگامسازی وضعیت پخشکننده با وضعیت جلسه و دریافت دستورات از کنترلکنندههایی بود که نیاز به واگذاری به متدهای پخشکننده مناسب داشتند. با AndroidX Media3، این کار مستقیماً توسط MediaSession و بدون نیاز به کانکتور انجام میشود.
حذف تمام ارجاعات و استفاده از MediaSessionConnector: اگر از اسکریپت خودکار برای انتقال کلاسها و بستههای ExoPlayer استفاده کردهاید، احتمالاً اسکریپت کد شما را در حالت غیرقابل کامپایل در رابطه با
MediaSessionConnectorقرار داده است که قابل حل نیست. اندروید استودیو هنگام تلاش برای ساخت یا شروع برنامه، کد معیوب را به شما نشان میدهد.در فایل
build.gradleکه وابستگیهای خود را در آن نگهداری میکنید، یک وابستگی پیادهسازی به ماژول جلسه AndroidX Media3 اضافه کنید و وابستگی قدیمی را حذف کنید:implementation "androidx.media3:media3-session:1.9.2"MediaSessionCompatرا باandroidx.media3.session.MediaSessionجایگزین کنید.در محل کدی که
MediaSessionCompatقدیمی را ایجاد کردهاید،androidx.media3.session.MediaSession.Builderبرای ساختMediaSessionاستفاده کنید. برای ساخت سازندهی جلسه، player را ارسال کنید .کاتلین
val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player).setCallback(MySessionCallback()).build()
جاوا
ExoPlayer player = new ExoPlayer.Builder(context).build(); mediaSession = new MediaSession.Builder(context, player).setCallback(new MySessionCallback()).build();
MySessionCallbackطبق نیاز برنامه خود پیادهسازی کنید. این اختیاری است. اگر میخواهید به کنترلرها اجازه دهید آیتمهای رسانهای را به پخشکننده اضافه کنند،MediaSession.Callback.onAddMediaItems()را پیادهسازی کنید. این متدها، متدهای API فعلی و قدیمی مختلفی را ارائه میدهند که آیتمهای رسانهای را برای پخش به صورت سازگار با نسخههای قبلی به پخشکننده اضافه میکنند. این شامل متدهایMediaController.set/addMediaItems()از کنترلر Media3 و همچنین متدهایTransportControls.prepareFrom*/playFrom*از API قدیمی است. یک پیادهسازی نمونه ازonAddMediaItemsرا میتوانید درPlaybackServiceبرنامه آزمایشی session پیدا کنید.جلسه رسانه را در محل کدی که جلسه خود را قبل از مهاجرت از بین بردهاید، منتشر کنید:
کاتلین
mediaSession?.run { player.release() release() mediaSession = null }
جاوا
if (mediaSession != null) { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; }
قابلیت MediaSessionConnector در Media3
جدول زیر APIهای Media3 را نشان میدهد که عملکردهایی را که قبلاً در MediaSessionConnector پیادهسازی شدهاند، مدیریت میکنند.
| رابط جلسه رسانهای | اندروید ایکس مدیا۳ |
|---|---|
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 مقدمهای خوب برای API و مدل برنامهنویسی ناهمزمان این سرویس ارائه میدهند.
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که وابستگیهای خود را در آن نگهداری میکنید، یک وابستگی پیادهسازی به ماژول جلسه AndroidX Media3 اضافه کنید و وابستگی قدیمی را حذف کنید:implementation "androidx.media3:media3-session:1.9.2"سرویس خود را طوری تغییر دهید که به جای
MediaLibraryServiceاز MediaLibraryService ارث بری کند.MediaBrowserServiceکه قبلاً گفته شد،MediaLibraryServiceباMediaBrowserServiceقدیمی سازگار است. بر این اساس، API گستردهتری که این سرویس به کلاینتها ارائه میدهد، همچنان یکسان است. بنابراین احتمالاً یک برنامه میتواند بیشتر منطق مورد نیاز برای پیادهسازیMediaBrowserServiceرا حفظ کرده و آن را برایMediaLibraryServiceجدید تطبیق دهد.تفاوتهای اصلی در مقایسه با نسخه قدیمی
MediaBrowserServiceCompatبه شرح زیر است:پیادهسازی متدهای چرخه حیات سرویس: متدهایی که باید روی خود سرویس بازنویسی شوند
onCreate/onDestroyهستند که در آن برنامه، session کتابخانه، پخشکننده و سایر منابع را تخصیص/رها میکند. علاوه بر متدهای استاندارد چرخه حیات سرویس، یک برنامه بایدonGetSession(MediaSession.ControllerInfo)بازنویسی کند تاMediaLibrarySessionرا که درonCreateساخته شده است، برگرداند.پیادهسازی MediaLibraryService.MediaLibrarySessionCallback: ساخت یک session نیاز به یک
MediaLibraryService.MediaLibrarySessionCallbackدارد که متدهای API دامنهی واقعی را پیادهسازی میکند. بنابراین به جای بازنویسی متدهای API سرویس قدیمی، متدهایMediaLibrarySession.Callbackرا بازنویسی خواهید کرد.سپس از این فراخوانی برای ساخت
MediaLibrarySessionاستفاده میشود:کاتلین
mediaLibrarySession = MediaLibrarySession.Builder(context, player, MySessionCallback()).build()
جاوا
mediaLibrarySession = new MediaLibrarySession.Builder(context, player, new MySessionCallback()).build();
API کامل MediaLibrarySessionCallback را در مستندات API پیدا کنید.
پیادهسازی
MediaSession.Callback.onAddMediaItems(): تابع فراخوانیonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)متدهای API فعلی و قدیمی مختلفی را ارائه میدهد که آیتمهای رسانهای را برای پخش به پخشکننده به روشی سازگار با نسخههای قبلی اضافه میکنند. این شامل متدهایMediaController.set/addMediaItems()از کنترلر Media3 و همچنین متدهایTransportControls.prepareFrom*/playFrom*از API قدیمی است. یک پیادهسازی نمونه از این تابع فراخوانی را میتوانید درPlaybackServiceاز برنامه آزمایشی session پیدا کنید.AndroidX Media3 به جای MediaBrowserCompat.MediaItem و MediaMetadataCompat از
androidx.media3.common.MediaItemاستفاده میکند. بخشهایی از کد شما که به کلاسهای قدیمی گره خوردهاند، باید متناسب با آن تغییر کنند یا بهMediaItemمدیا3 نگاشت شوند.مدل برنامهنویسی ناهمگام عمومی در مقایسه با رویکرد
ResultجداشدنیMediaBrowserServiceCompatبهFuturesتغییر یافت . پیادهسازی سرویس شما میتواند به جای جدا کردن یک نتیجه، یکListenableFutureناهمگام برگرداند یا یک Future فوری برای بازگرداندن مستقیم یک مقدار برگرداند .
حذف PlayerNotificationManager
سرویس MediaLibraryService به طور خودکار از اعلانهای رسانهای پشتیبانی میکند و PlayerNotificationManager میتوان هنگام استفاده از MediaLibraryService یا MediaSessionService حذف کرد.
یک برنامه میتواند با تنظیم یک MediaNotification.Provider سفارشی در onCreate() که جایگزین DefaultMediaNotificationProvider میشود، اعلان را سفارشی کند . سپس MediaLibraryService در صورت نیاز، شروع سرویس را در پیشزمینه بر عهده میگیرد.
با override کردن MediaLibraryService.updateNotification() ، یک برنامه میتواند مالکیت کامل ارسال یک اعلان و شروع/توقف سرویس در پیشزمینه را در صورت نیاز به دست بگیرد.
انتقال کد کلاینت با استفاده از MediaBrowser
با AndroidX Media3، یک MediaBrowser رابطهای MediaController/Player را پیادهسازی میکند و میتواند علاوه بر مرور کتابخانه رسانه، برای کنترل پخش رسانه نیز مورد استفاده قرار گیرد. اگر در دنیای قدیمی مجبور بودید یک MediaBrowserCompat و یک MediaControllerCompat ایجاد کنید، میتوانید همین کار را تنها با استفاده از MediaBrowser در Media3 انجام دهید.
میتوان یک MediaBrowser ساخت و منتظر اتصال به سرویس در حال برقراری ماند:
کاتلین
scope.launch { val sessionToken = SessionToken(context, ComponentName(context, "MusicService")) browser = MediaBrowser.Builder(context, sessionToken) .setListener(BrowserListener()) .buildAsync() .await() }
جاوا
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, "MusicService")); ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken) .setListener(new BrowserListener()) .buildAsync();
برای یادگیری نحوه ایجاد یک MediaController برای کنترل پخش در پسزمینه، به بخش Control playback در جلسه رسانه نگاهی بیندازید.
مراحل بعدی و پاکسازی
خطاهای API ناپایدار
پس از مهاجرت به Media3، ممکن است خطاهای lint مربوط به کاربردهای ناپایدار API را مشاهده کنید. استفاده از این APIها بیخطر است و خطاهای lint محصول جانبی تضمینهای سازگاری دودویی جدید ما هستند. اگر به سازگاری دودویی سختگیرانهای نیاز ندارید، این خطاها را میتوان با حاشیهنویسی @OptIn به طور ایمن سرکوب کرد.
پیشینه
نه ExoPlayer نسخه ۱ و نه نسخه ۲ هیچکدام تضمین دقیقی در مورد سازگاری باینری کتابخانه بین نسخههای بعدی ارائه ندادند. سطح API ExoPlayer از نظر طراحی بسیار بزرگ است تا به برنامهها اجازه دهد تقریباً هر جنبهای از پخش را سفارشی کنند. نسخههای بعدی ExoPlayer گهگاه تغییر نام نمادها یا سایر تغییرات مخرب (مثلاً روشهای جدید مورد نیاز در رابطها) را معرفی میکردند. در بیشتر موارد، این نقصها با معرفی نماد جدید در کنار منسوخ کردن نماد قدیمی برای چند نسخه کاهش مییافت تا به توسعهدهندگان زمان داده شود تا کاربردهای خود را منتقل کنند، اما این همیشه امکانپذیر نبود.
این تغییرات اساسی منجر به دو مشکل برای کاربران کتابخانههای ExoPlayer نسخه ۱ و ۲ شد:
- ارتقاء به نسخه ExoPlayer میتواند باعث توقف کامپایل کد شود.
- برنامهای که هم به طور مستقیم و هم از طریق یک کتابخانه واسط به ExoPlayer وابسته بود، باید اطمینان حاصل میکرد که هر دو وابستگی نسخه یکسانی دارند، در غیر این صورت ناسازگاریهای باینری میتوانست منجر به خرابی در زمان اجرا شود.
بهبودها در مدیا۳
Media3 سازگاری دودویی را برای زیرمجموعهای از سطح API تضمین میکند. بخشهایی که سازگاری دودویی را تضمین نمیکنند با @UnstableApi مشخص شدهاند. برای روشن شدن این تمایز، استفاده از نمادهای API ناپایدار، مگر اینکه با @OptIn حاشیهنویسی شوند، خطای lint ایجاد میکند.
پس از مهاجرت از ExoPlayer نسخه ۲ به Media3، ممکن است خطاهای lint ناپایدار API زیادی مشاهده کنید. این ممکن است باعث شود که به نظر برسد Media3 نسبت به ExoPlayer نسخه ۲ «پایداری کمتری» دارد. اما اینطور نیست. بخشهای «ناپایدار» API Media3 همان سطح پایداری کل سطح API ExoPlayer نسخه ۲ را دارند و ضمانتهای سطح API پایدار Media3 به هیچ وجه در ExoPlayer نسخه ۲ موجود نیست. تفاوت این است که اکنون یک خطای lint شما را از سطوح مختلف پایداری مطلع میکند.
خطاهای ناپایدار lint در API را مدیریت کنید
برای جزئیات بیشتر در مورد نحوه حاشیهنویسی کاربردهای جاوا و کاتلین از APIهای ناپایدار با استفاده از @OptIn ، به بخش عیبیابی این خطاهای Lint مراجعه کنید.
API های منسوخ شده
ممکن است متوجه شده باشید که فراخوانیهای مربوط به APIهای منسوخشده در اندروید استودیو خط خوردهاند. توصیه میکنیم چنین فراخوانیهایی را با جایگزین مناسب جایگزین کنید. برای مشاهدهی JavaDoc که به شما میگوید از کدام API استفاده کنید، نشانگر ماوس را روی نماد نگه دارید.

نمونه کدها و برنامههای نمایشی
- برنامه آزمایشی جلسه AndroidX Media3 (موبایل و WearOS)
- اقدامات سفارشی
- اعلان رابط کاربری سیستم، دکمه رسانه/بلوتوث
- کنترل پخش دستیار گوگل
- UAMP: پخشکننده رسانه اندروید (شاخه media3) (موبایل، AutomotiveOS)
- اعلان رابط کاربری سیستم، دکمه مدیا/بلوتوث، از سرگیری پخش
- کنترل پخش با دستیار گوگل/WearOS
- AutomotiveOS: دستور سفارشی و ورود به سیستم
برنامههایی که در حال حاضر از کتابخانه مستقل com.google.android.exoplayer2 و androidx.media استفاده میکنند، باید به androidx.media3 مهاجرت کنند. از اسکریپت مهاجرت برای انتقال فایلهای ساخت gradle، فایلهای منبع جاوا و کاتلین و فایلهای طرحبندی XML از ExoPlayer 2.19.1 به AndroidX Media3 1.1.1 استفاده کنید.
نمای کلی
قبل از مهاجرت، بخشهای زیر را مرور کنید تا در مورد مزایای APIهای جدید، APIهای مورد نیاز برای مهاجرت و پیشنیازهایی که پروژه برنامه شما باید داشته باشد، بیشتر بدانید.
چرا به Jetpack Media3 مهاجرت کنیم؟
- این خانه جدید ExoPlayer است، در حالی که
com.google.android.exoplayer2دیگر پشتیبانی نمیشود. - با استفاده از
MediaBrowser/MediaControllerبه رابط برنامهنویسی کاربردی پخشکننده (Player API) از طریق کامپوننتها/فرآیندها دسترسی پیدا کنید. - از قابلیتهای توسعهیافتهی
MediaSessionوMediaControllerAPI استفاده کنید. - قابلیتهای پخش را با کنترل دسترسی دقیق تبلیغ کنید.
- با حذف
MediaSessionConnectorوPlayerNotificationManagerبرنامه خود را ساده کنید . - Backwards compatible with media-compat client APIs (
MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)
APIهای رسانهای برای مهاجرت به 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منتقل کنید.
پیشنیازها
مطمئن شوید که پروژه شما تحت کنترل منبع است
مطمئن شوید که میتوانید به راحتی تغییرات اعمال شده توسط ابزارهای مهاجرت اسکریپتشده را به حالت اولیه برگردانید. اگر هنوز پروژه خود را تحت کنترل منبع ندارید، اکنون زمان مناسبی برای شروع آن است. اگر به هر دلیلی نمیخواهید این کار را انجام دهید، قبل از شروع مهاجرت، یک نسخه پشتیبان از پروژه خود تهیه کنید.
برنامه خود را بهروزرسانی کنید
توصیه میکنیم پروژه خود را بهروزرسانی کنید تا از جدیدترین نسخه کتابخانه ExoPlayer استفاده کند و هرگونه فراخوانی به متدهای منسوخشده را حذف کنید. اگر قصد دارید از اسکریپت برای مهاجرت استفاده کنید ، باید نسخهای را که به آن بهروزرسانی میکنید با نسخهای که توسط اسکریپت مدیریت میشود، مطابقت دهید.
compileSdkVersion برنامه خود را حداقل به ۳۲ افزایش دهید.
Gradle و افزونهی Gradle اندروید استودیو را به آخرین نسخهای که با وابستگیهای بهروزرسانیشدهی بالا کار میکند، ارتقا دهید . برای مثال:
- نسخه افزونه اندروید Gradle: 7.1.0
- نسخه گرادل: ۷.۴
تمام عبارات ورودی wildcard که از علامت ستاره (*) استفاده میکنند را جایگزین کنید و از عبارات ورودی کامل استفاده کنید: عبارات ورودی wildcard را حذف کنید و از اندروید استودیو برای وارد کردن عبارات کامل (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 اندروید که به زبان جاوا یا کاتلین نوشته شده است، اعمال میکند.
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 این مراحل دستی را انجام دهید:
- بررسی کنید که اسکریپت چگونه کد شما را تغییر داده است : از یک ابزار diff استفاده کنید و مشکلات احتمالی را برطرف کنید (اگر فکر میکنید اسکریپت یک مشکل کلی دارد که بدون عبور از گزینه
-fایجاد شده است، ثبت یک اشکال را در نظر بگیرید). - پروژه را بسازید : یا از
./gradlew clean build استفاده کنید یا در اندروید استودیو مسیر File > Sync Project with Gradle Files را انتخاب کنید، سپس Build > Clean project و در نهایت Build > Rebuild project را انتخاب کنید (ساخت خود را در تب 'Build - Build Output' در اندروید استودیو مانیتور کنید).
مراحل پیگیری توصیه شده:
- رفع خطاهای مربوط به عدم استفاده از APIهای ناپایدار در هنگام ثبتنام .
- جایگزینی فراخوانیهای API منسوخشده : از API جایگزین پیشنهادی استفاده کنید. در اندروید استودیو، نشانگر ماوس را روی هشدار نگه دارید و برای یافتن اینکه به جای فراخوانی مشخصشده از چه چیزی استفاده کنید، به JavaDoc نماد منسوخشده مراجعه کنید.
- مرتبسازی دستورات ایمپورت : پروژه را در اندروید استودیو باز کنید، سپس روی گره پوشه پکیج در نمایشگر پروژه کلیک راست کرده و روی پکیجهایی که حاوی فایلهای منبع تغییر یافته هستند، گزینه Optimize import را انتخاب کنید.
MediaSessionConnector را با androidx.media3.session.MediaSession جایگزین کنید
در دنیای قدیمی MediaSessionCompat ، MediaSessionConnector مسئول همگامسازی وضعیت پخشکننده با وضعیت جلسه و دریافت دستورات از کنترلکنندههایی بود که نیاز به واگذاری به متدهای پخشکننده مناسب داشتند. با AndroidX Media3، این کار مستقیماً توسط MediaSession و بدون نیاز به کانکتور انجام میشود.
حذف تمام ارجاعات و استفاده از MediaSessionConnector: اگر از اسکریپت خودکار برای انتقال کلاسها و بستههای ExoPlayer استفاده کردهاید، احتمالاً اسکریپت کد شما را در حالت غیرقابل کامپایل در رابطه با
MediaSessionConnectorقرار داده است که قابل حل نیست. اندروید استودیو هنگام تلاش برای ساخت یا شروع برنامه، کد معیوب را به شما نشان میدهد.در فایل
build.gradleکه وابستگیهای خود را در آن نگهداری میکنید، یک وابستگی پیادهسازی به ماژول جلسه AndroidX Media3 اضافه کنید و وابستگی قدیمی را حذف کنید:implementation "androidx.media3:media3-session:1.9.2"MediaSessionCompatرا باandroidx.media3.session.MediaSessionجایگزین کنید.در محل کدی که
MediaSessionCompatقدیمی را ایجاد کردهاید،androidx.media3.session.MediaSession.Builderبرای ساختMediaSessionاستفاده کنید. برای ساخت سازندهی جلسه، player را ارسال کنید .کاتلین
val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player).setCallback(MySessionCallback()).build()
جاوا
ExoPlayer player = new ExoPlayer.Builder(context).build(); mediaSession = new MediaSession.Builder(context, player).setCallback(new MySessionCallback()).build();
MySessionCallbackطبق نیاز برنامه خود پیادهسازی کنید. این اختیاری است. اگر میخواهید به کنترلرها اجازه دهید آیتمهای رسانهای را به پخشکننده اضافه کنند،MediaSession.Callback.onAddMediaItems()را پیادهسازی کنید. این متدها، متدهای API فعلی و قدیمی مختلفی را ارائه میدهند که آیتمهای رسانهای را برای پخش به صورت سازگار با نسخههای قبلی به پخشکننده اضافه میکنند. این شامل متدهایMediaController.set/addMediaItems()از کنترلر Media3 و همچنین متدهایTransportControls.prepareFrom*/playFrom*از API قدیمی است. یک پیادهسازی نمونه ازonAddMediaItemsرا میتوانید درPlaybackServiceبرنامه آزمایشی session پیدا کنید.جلسه رسانه را در محل کدی که جلسه خود را قبل از مهاجرت از بین بردهاید، منتشر کنید:
کاتلین
mediaSession?.run { player.release() release() mediaSession = null }
جاوا
if (mediaSession != null) { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; }
قابلیت MediaSessionConnector در Media3
جدول زیر APIهای Media3 را نشان میدهد که عملکردهایی را که قبلاً در MediaSessionConnector پیادهسازی شدهاند، مدیریت میکنند.
| رابط جلسه رسانهای | اندروید ایکس مدیا۳ |
|---|---|
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 مقدمهای خوب برای API و مدل برنامهنویسی ناهمزمان این سرویس ارائه میدهند.
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که وابستگیهای خود را در آن نگهداری میکنید، یک وابستگی پیادهسازی به ماژول جلسه AndroidX Media3 اضافه کنید و وابستگی قدیمی را حذف کنید:implementation "androidx.media3:media3-session:1.9.2"سرویس خود را طوری تغییر دهید که به جای
MediaLibraryServiceاز MediaLibraryService ارث بری کند.MediaBrowserServiceکه قبلاً گفته شد،MediaLibraryServiceباMediaBrowserServiceقدیمی سازگار است. بر این اساس، API گستردهتری که این سرویس به کلاینتها ارائه میدهد، همچنان یکسان است. بنابراین احتمالاً یک برنامه میتواند بیشتر منطق مورد نیاز برای پیادهسازیMediaBrowserServiceرا حفظ کرده و آن را برایMediaLibraryServiceجدید تطبیق دهد.تفاوتهای اصلی در مقایسه با نسخه قدیمی
MediaBrowserServiceCompatبه شرح زیر است:پیادهسازی متدهای چرخه حیات سرویس: متدهایی که باید روی خود سرویس بازنویسی شوند
onCreate/onDestroyهستند که در آن برنامه، session کتابخانه، پخشکننده و سایر منابع را تخصیص/رها میکند. علاوه بر متدهای استاندارد چرخه حیات سرویس، یک برنامه بایدonGetSession(MediaSession.ControllerInfo)بازنویسی کند تاMediaLibrarySessionرا که درonCreateساخته شده است، برگرداند.پیادهسازی MediaLibraryService.MediaLibrarySessionCallback: ساخت یک session نیاز به یک
MediaLibraryService.MediaLibrarySessionCallbackدارد که متدهای API دامنهی واقعی را پیادهسازی میکند. بنابراین به جای بازنویسی متدهای API سرویس قدیمی، متدهایMediaLibrarySession.Callbackرا بازنویسی خواهید کرد.سپس از این فراخوانی برای ساخت
MediaLibrarySessionاستفاده میشود:کاتلین
mediaLibrarySession = MediaLibrarySession.Builder(context, player, MySessionCallback()).build()
جاوا
mediaLibrarySession = new MediaLibrarySession.Builder(context, player, new MySessionCallback()).build();
API کامل MediaLibrarySessionCallback را در مستندات API پیدا کنید.
پیادهسازی
MediaSession.Callback.onAddMediaItems(): تابع فراخوانیonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)متدهای API فعلی و قدیمی مختلفی را ارائه میدهد که آیتمهای رسانهای را برای پخش به پخشکننده به روشی سازگار با نسخههای قبلی اضافه میکنند. این شامل متدهایMediaController.set/addMediaItems()از کنترلر Media3 و همچنین متدهایTransportControls.prepareFrom*/playFrom*از API قدیمی است. یک پیادهسازی نمونه از این تابع فراخوانی را میتوانید درPlaybackServiceاز برنامه آزمایشی session پیدا کنید.AndroidX Media3 به جای MediaBrowserCompat.MediaItem و MediaMetadataCompat از
androidx.media3.common.MediaItemاستفاده میکند. بخشهایی از کد شما که به کلاسهای قدیمی گره خوردهاند، باید متناسب با آن تغییر کنند یا بهMediaItemمدیا3 نگاشت شوند.مدل برنامهنویسی ناهمگام عمومی در مقایسه با رویکرد
ResultجداشدنیMediaBrowserServiceCompatبهFuturesتغییر یافت . پیادهسازی سرویس شما میتواند به جای جدا کردن یک نتیجه، یکListenableFutureناهمگام برگرداند یا یک Future فوری برای بازگرداندن مستقیم یک مقدار برگرداند .
حذف PlayerNotificationManager
سرویس MediaLibraryService به طور خودکار از اعلانهای رسانهای پشتیبانی میکند و PlayerNotificationManager میتوان هنگام استفاده از MediaLibraryService یا MediaSessionService حذف کرد.
یک برنامه میتواند با تنظیم یک MediaNotification.Provider سفارشی در onCreate() که جایگزین DefaultMediaNotificationProvider میشود، اعلان را سفارشی کند . سپس MediaLibraryService در صورت نیاز، شروع سرویس را در پیشزمینه بر عهده میگیرد.
با override کردن MediaLibraryService.updateNotification() ، یک برنامه میتواند مالکیت کامل ارسال یک اعلان و شروع/توقف سرویس در پیشزمینه را در صورت نیاز به دست بگیرد.
انتقال کد کلاینت با استفاده از MediaBrowser
با AndroidX Media3، یک MediaBrowser رابطهای MediaController/Player را پیادهسازی میکند و میتواند علاوه بر مرور کتابخانه رسانه، برای کنترل پخش رسانه نیز مورد استفاده قرار گیرد. اگر در دنیای قدیمی مجبور بودید یک MediaBrowserCompat و یک MediaControllerCompat ایجاد کنید، میتوانید همین کار را تنها با استفاده از MediaBrowser در Media3 انجام دهید.
A MediaBrowser can be built and await for the connection to the service being established:
کاتلین
scope.launch { val sessionToken = SessionToken(context, ComponentName(context, "MusicService")) browser = MediaBrowser.Builder(context, sessionToken) .setListener(BrowserListener()) .buildAsync() .await() }
جاوا
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, "MusicService")); ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken) .setListener(new BrowserListener()) .buildAsync();
Take a look into Control playback in the media session to learn how to create a MediaController for controlling playback in the background.
Further steps and clean up
Unstable API errors
After migrating to Media3, you may see lint errors about unstable API usages. These APIs are safe to use and the lint errors are a by-product of our new binary compatibility guarantees. If you don't require strict binary compatibility, these errors can be safely suppressed with an @OptIn annotation.
پیشینه
Neither ExoPlayer v1 or v2 provided strict guarantees about binary compatibility of the library between subsequent versions. The ExoPlayer API surface is very large by design, in order to allow apps to customize nearly every aspect of playback. Subsequent versions of ExoPlayer would occasionally introduce symbol renames or other breaking changes (eg new required methods on interfaces). In most cases these breakages were mitigated by introducing the new symbol alongside deprecating the old symbol for a few versions, to allow developers time to migrate their usages, but this wasn't always possible.
These breaking changes resulted in two problems for users of the ExoPlayer v1 and v2 libraries:
- An upgrade from to the ExoPlayer version could cause code to stop compiling.
- An app that depended on ExoPlayer both directly and via an intermediate library had to ensure that both dependencies were the same version, otherwise binary incompatibilities could result in runtime crashes.
Improvements in Media3
Media3 guarantees binary compatibility for a subset of the API surface. The parts that don't guarantee binary compatibility are marked with @UnstableApi . In order to make this distinction clear, usages of unstable API symbols generate a lint error unless they are annotated with @OptIn .
After migrating from ExoPlayer v2 to Media3, you may see a lot of unstable API lint errors. This may make it seem like Media3 is 'less stable' than ExoPlayer v2. This is not the case. The 'unstable' parts of the Media3 API have the same level of stability as the whole of the ExoPlayer v2 API surface, and the guarantees of the stable Media3 API surface are not available in ExoPlayer v2 at all. The difference is simply that a lint error now alerts you to the different levels of stability.
Handle unstable API lint errors
See the troubleshooting section on these lint errors for details on how to annotate Java and Kotlin usages of unstable APIs with @OptIn .
Deprecated APIs
You may notice that calls to deprecated APIs are struck-through in Android Studio. We recommend replacing such calls with the appropriate alternative. Hover over the symbol to see the JavaDoc that tells which API to use instead.

Code samples and demo apps
- AndroidX Media3 session demo app (mobile and WearOS)
- Custom actions
- System UI notification, MediaButton/BT
- Google Assistant playback control
- UAMP: Android Media Player (branch media3) (mobile, AutomotiveOS)
- System UI notification, MediaButton/BT, Playback resumption
- Google Assistant/WearOS playback control
- AutomotiveOS: custom command and sign-in