برنامههایی که در حال حاضر از کتابخانه مستقل 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' در اندروید استودیو زیر نظر داشته باشید).
مراحل پیگیری توصیه شده:
- رفع خطاهای مربوط به عدم استفاده از 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.8.0"MediaSessionCompatرا باandroidx.media3.session.MediaSessionجایگزین کنید.در محل کدی که
MediaSessionCompatقدیمی را ایجاد کردهاید،androidx.media3.session.MediaSession.Builderبرای ساختMediaSessionاستفاده کنید. برای ساخت سازندهی جلسه ، player را ارسال کنید .val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(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 }
قابلیت 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.8.0"سرویس خود را طوری تغییر دهید
MediaLibraryServiceبه جایMediaBrowserServiceاز MediaLibraryService ارث بری کند. همانطور که قبلاً گفته شد،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(this, player, 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::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 برای کنترل پخش در پسزمینه، به بخش 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: دستور سفارشی و ورود به سیستم