برنامههایی که در حال حاضر از کتابخانه مستقل com.google.android.exoplayer2
و androidx.media
استفاده میکنند باید به androidx.media3
مهاجرت کنند. از اسکریپت مهاجرت برای انتقال فایل های ساخت gradle، فایل های منبع جاوا و Kotlin و فایل های طرح بندی XML از ExoPlayer 2.19.1
به AndroidX Media3 1.1.1
استفاده کنید.
نمای کلی
قبل از مهاجرت، بخشهای زیر را مرور کنید تا در مورد مزایای APIهای جدید، APIهای انتقال و پیش نیازهایی که پروژه برنامه شما باید رعایت کند بیشتر بدانید.
چرا به Jetpack Media3 مهاجرت کنید
- این خانه جدید ExoPlayer است، در حالی که
com.google.android.exoplayer2
متوقف شده است. - با
MediaBrowser
/MediaController
به API Player در بین اجزا/فرآیندها دسترسی داشته باشید. - از قابلیت های توسعه یافته
MediaSession
وMediaController
API استفاده کنید. - قابلیت های پخش را با کنترل دسترسی دقیق تبلیغ کنید.
- برنامه خود را با حذف
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+
)
برای استفاده ازandroidx.media3.session.MediaBrowser
باandroidx.media3.common.MediaItem
، کد سرویس گیرنده را با استفاده ازMediaBrowserCompat
یاMediaControllerCompat
منتقل کنید.
پیش نیازها
مطمئن شوید که پروژه شما تحت کنترل منبع است
اطمینان حاصل کنید که می توانید به راحتی تغییرات اعمال شده توسط ابزارهای انتقال اسکریپت را برگردانید. اگر هنوز پروژه خود را تحت کنترل منبع ندارید، اکنون زمان خوبی برای شروع آن است. اگر به دلایلی نمیخواهید این کار را انجام دهید، قبل از شروع مهاجرت، یک نسخه پشتیبان از پروژه خود تهیه کنید.
برنامه خود را به روز کنید
توصیه میکنیم پروژه خود را بهروزرسانی کنید تا از جدیدترین نسخه کتابخانه ExoPlayer استفاده کنید و هرگونه تماس با روشهای منسوخ را حذف کنید. اگر میخواهید از اسکریپت برای انتقال استفاده کنید ، باید نسخهای را که بهروزرسانی میکنید با نسخهای که توسط اسکریپت مدیریت میشود مطابقت دهید.
کامپایلSdkVersion برنامه خود را به حداقل 32 افزایش دهید.
Gradle و افزونه Android Studio Gradle را به نسخه اخیر ارتقا دهید که با وابستگی های به روز شده از بالا کار می کند. به عنوان مثال:
- نسخه پلاگین اندروید Gradle: 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
را تسهیل می کند. این اسکریپت برخی از بررسیهای اعتبارسنجی را روی پروژه شما اعمال میکند و در صورت عدم موفقیت اعتبار، هشدارها را چاپ میکند. در غیر این صورت، نگاشت کلاس ها و بسته های تغییر نام یافته را در منابع پروژه 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 را انتخاب کنید (بیلد خود را در تب «Build - Build Output» زیر نظر بگیرید. اندروید استودیو .
مراحل پیشنهادی پیگیری:
- خطاهای مربوط به استفاده از APIهای ناپایدار را حل کنید.
- جایگزینی تماسهای API منسوخ شده : از API جایگزین پیشنهادی استفاده کنید. نشانگر را روی اخطار در Android Studio نگه دارید و با JavaDoc نماد منسوخ شده مشورت کنید تا دریابید که به جای تماس معین از چه چیزی استفاده کنید.
- مرتب سازی عبارت های import : پروژه را در Android Studio باز کنید، سپس روی گره پوشه بسته در نمایشگر پروژه کلیک راست کرده و Optimize imports on بسته هایی که حاوی فایل های منبع تغییر یافته هستند را انتخاب کنید.
MediaSessionConnector
با androidx.media3.session.MediaSession
جایگزین کنید
در دنیای قدیمی MediaSessionCompat
، MediaSessionConnector
مسئول همگام سازی وضعیت پخش کننده با وضعیت جلسه و دریافت دستورات از کنترلرهایی بود که نیاز به تفویض به روش های پخش مناسب داشتند. با AndroidX Media3، این کار توسط MediaSession
مستقیماً بدون نیاز به اتصال انجام می شود.
حذف همه مراجع و استفاده از MediaSessionConnector: اگر از اسکریپت خودکار برای انتقال کلاسها و بستههای ExoPlayer استفاده کردهاید، احتمالاً اسکریپت کد شما را در وضعیت غیرقابل کامپایل در رابطه با
MediaSessionConnector
گذاشته است که قابل حل نیست. وقتی می خواهید برنامه را بسازید یا راه اندازی کنید، Android Studio کد شکسته را به شما نشان می دهد.در فایل
build.gradle
که در آن وابستگی های خود را حفظ می کنید، یک وابستگی پیاده سازی را به ماژول جلسه AndroidX Media3 اضافه کنید و وابستگی قدیمی را حذف کنید:implementation "androidx.media3:media3-session:1.4.1"
MediaSessionCompat
باandroidx.media3.session.MediaSession
جایگزین کنید.در سایت کدی که
MediaSessionCompat
قدیمی را ایجاد کردهاید، ازandroidx.media3.session.MediaSession.Builder
برای ساختMediaSession
استفاده کنید. برای ساخت Session Builder از بازیکن عبور دهید .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
برنامه نمایشی جلسه پیدا کنید.جلسه رسانه را در سایت کدی که قبل از انتقال جلسه خود را از بین برده اید، آزاد کنید:
mediaSession?.run { player.release() release() mediaSession = null }
قابلیت MediaSessionConnector
در Media3
جدول زیر APIهای Media3 را نشان میدهد که عملکردهایی را که قبلاً در MediaSessionConnector
پیادهسازی شدهاند، مدیریت میکنند.
MediaSessionConnector | AndroidX 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
فوق کلاس آن مقدمه خوبی برای API و مدل برنامه نویسی ناهمزمان این سرویس ارائه می دهد.
MediaLibraryService
به طور معکوس با MediaBrowserService
سازگار است. یک برنامه مشتری که از MediaBrowserCompat
یا MediaControllerCompat
استفاده می کند، هنگام اتصال به MediaLibraryService
بدون تغییر کد به کار خود ادامه می دهد. برای یک کلاینت، مشخص است که برنامه شما از MediaLibraryService
یا یک MediaBrowserServiceCompat
قدیمی استفاده می کند.
![نمودار مؤلفه برنامه با سرویس، فعالیت و برنامه های خارجی.](https://developer.android.com/static/media/images/overview.png?authuser=2&hl=fa)
برای اینکه سازگاری به عقب کار کند، باید هر دو رابط سرویس را با سرویس خود در
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.4.1"
همانطور که قبلاً گفته شد
MediaLibraryService
MediaLibraryService
MediaBrowserService
MediaBrowserService
سازگار است. بر این اساس، API گستردهتری که این سرویس به مشتریان ارائه میکند، همچنان یکسان است. بنابراین این احتمال وجود دارد که یک برنامه بتواند بیشتر منطق مورد نیاز برای اجرایMediaBrowserService
را حفظ کند و آن را برایMediaLibraryService
جدید تطبیق دهد.تفاوت های اصلی در مقایسه با
MediaBrowserServiceCompat
قدیمی به شرح زیر است:روشهای چرخه عمر سرویس را پیادهسازی کنید: روشهایی که باید روی خود سرویس نادیده گرفته شوند
onCreate/onDestroy
هستند، جایی که یک برنامه جلسه کتابخانه، پخشکننده و سایر منابع را اختصاص/آزاد میکند. علاوه بر روشهای استاندارد چرخه عمر سرویس، یک برنامه بایدonGetSession(MediaSession.ControllerInfo)
لغو کند تاMediaLibrarySession
ساخته شده درonCreate
را برگرداند.Implement MediaLibraryService.MediaLibrarySessionCallback: ایجاد یک جلسه به
MediaLibraryService.MediaLibrarySessionCallback
نیاز دارد که متدهای API دامنه واقعی را پیاده سازی می کند. بنابراین به جای نادیده گرفتن متدهای API سرویس قدیمی، روش هایMediaLibrarySession.Callback
را لغو می کنید.سپس از callback برای ساخت
MediaLibrarySession
استفاده می شود:mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()
API کامل MediaLibrarySessionCallback را در اسناد API پیدا کنید.
Implement
MediaSession.Callback.onAddMediaItems()
: پاسخ به تماسonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)
روشهای مختلف API فعلی و قدیمی را ارائه میکند که آیتمهای رسانهای را به پخش کننده برای پخش به روشی سازگار با عقب اضافه میکند. این شامل متدهایMediaController.set/addMediaItems()
کنترلر Media3 و همچنین متدهایTransportControls.prepareFrom*/playFrom*
در API قدیمی است. نمونهای از اجرای callback را میتوانید درPlaybackService
برنامه نمایشی جلسه پیدا کنید.AndroidX Media3 از
androidx.media3.common.MediaItem
به جای MediaBrowserCompat.MediaItem و MediaMetadataCompat استفاده می کند. بخشهایی از کد شما که به کلاسهای قدیمی مرتبط است باید بر اساس آن تغییر کند یا به جای آن به Media3MediaItem
نگاشت شود.مدل برنامهنویسی
Futures
عمومی برخلاف رویکردResult
قابل جداسازیMediaBrowserServiceCompat
به Futures تغییر کرد. پیادهسازی سرویس شما میتواند به جای جدا کردن یک نتیجه، یک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
برای کنترل پخش در پسزمینه، به Control playback در جلسه رسانه نگاهی بیندازید.
مراحل بعدی و پاکسازی
خطاهای ناپایدار API
پس از مهاجرت به Media3، ممکن است خطاهای پرزهایی در مورد استفاده های ناپایدار API مشاهده کنید. استفاده از این API ها ایمن است و خطاهای پرز محصول جانبی تضمین های سازگاری باینری جدید ما هستند. اگر به سازگاری دقیق باینری نیاز ندارید، این خطاها را می توان با یک حاشیه نویسی @OptIn
با خیال راحت سرکوب کرد.
پس زمینه
هیچ کدام ExoPlayer v1 یا v2 تضمین های دقیقی در مورد سازگاری باینری کتابخانه بین نسخه های بعدی ارائه نکردند. سطح API ExoPlayer از نظر طراحی بسیار بزرگ است تا به برنامه ها اجازه دهد تقریباً هر جنبه ای از پخش را سفارشی کنند. نسخههای بعدی ExoPlayer گاهی اوقات تغییر نام نمادها یا سایر تغییرات قطعی را معرفی میکنند (مثلاً روشهای جدید مورد نیاز در رابطها). در بیشتر موارد، این شکستگیها با معرفی نماد جدید در کنار حذف نماد قدیمی برای چند نسخه کاهش مییابد تا به توسعهدهندگان فرصت داده شود تا کاربردهای خود را تغییر دهند، اما این همیشه ممکن نبود.
این تغییرات شکسته منجر به دو مشکل برای کاربران کتابخانههای ExoPlayer v1 و v2 شد:
- ارتقا از نسخه ExoPlayer می تواند باعث توقف کامپایل کد شود.
- برنامهای که هم مستقیماً و هم از طریق یک کتابخانه میانی به ExoPlayer وابسته بود باید اطمینان حاصل میکرد که هر دو وابستگی یک نسخه هستند، در غیر این صورت ناسازگاریهای باینری میتواند منجر به خرابی زمان اجرا شود.
بهبود در Media3
Media3 سازگاری باینری را برای یک زیر مجموعه از سطح API تضمین می کند. قسمت هایی که سازگاری باینری را تضمین نمی کنند با @UnstableApi
علامت گذاری شده اند. به منظور روشن کردن این تمایز، استفاده از نمادهای API ناپایدار یک خطای پرز ایجاد می کند، مگر اینکه با @OptIn
حاشیه نویسی شده باشند.
پس از مهاجرت از ExoPlayer v2 به Media3، ممکن است خطاهای پرز ناپایدار API زیادی را مشاهده کنید. این ممکن است به نظر برسد که Media3 نسبت به ExoPlayer v2 «پایدارتر» است. اینطور نیست. بخشهای «ناپایدار» Media3 API همان سطح پایداری کل سطح API ExoPlayer v2 را دارند و تضمینهای سطح پایدار Media3 API اصلاً در ExoPlayer نسخه 2 موجود نیست. تفاوت در این است که اکنون یک خطای پرز به شما در مورد سطوح مختلف پایداری هشدار می دهد.
خطاهای پرز ناپایدار API را مدیریت کنید
برای جزئیات نحوه حاشیه نویسی استفاده از جاوا و کاتلین از APIهای ناپایدار با @OptIn
به بخش عیب یابی در این خطاهای پرز مراجعه کنید.
API های منسوخ شده
ممکن است متوجه شوید که تماسها با APIهای منسوخ شده در Android Studio انجام میشود. توصیه می کنیم چنین تماس هایی را با جایگزین مناسب جایگزین کنید. ماوس را روی نماد نگه دارید تا JavaDoc را ببینید که به شما می گوید از کدام API استفاده کنید.
![اسکرین شات: نحوه نمایش JavaDoc با روش جایگزین منسوخ](https://developer.android.com/static/media/media3/exoplayer/images/deprecation.png?authuser=2&hl=fa)
نمونه کد و برنامه های آزمایشی
- برنامه نمایشی جلسه AndroidX Media3 (موبایل و WearOS)
- اقدامات سفارشی
- اعلان رابط کاربری سیستم، MediaButton/BT
- کنترل پخش Google Assistant
- UAMP: Android Media Player (شاخه media3) (موبایل، AutomotiveOS)
- اعلان رابط کاربری سیستم، MediaButton/BT، ازسرگیری پخش
- کنترل پخش Google Assistant/WearOS
- AutomotiveOS: فرمان سفارشی و ورود به سیستم