برنامههایی که درحالحاضر از کتابخانه مستقل com.google.android.exoplayer2
و androidx.media استفاده میکنند باید به androidx.media3 منتقل شوند. از
اسکریپت انتقال برای انتقال فایلهای ساخت gradle، فایلهای منبع جاوا و
Kotlin، و فایلهای طرحبندی XML از ExoPlayer
2.19.1 به AndroidX Media3 1.1.1 استفاده کنید.
نمای کلی
قبلاز انتقال، بخشهای زیر را مرور کنید تا درباره مزایای میاناهای برنامهسازی کاربردی جدید، میاناهای برنامهسازی کاربردی برای انتقال، و پیشنیازهایی که پروژه برنامهتان باید داشته باشد بیشتر بدانید.
چرا باید به Jetpack Media3 مهاجرت کرد
- این خانه جدید ExoPlayer است، درحالیکه
com.google.android.exoplayer2متوقف شده است. - دسترسی به میانای برنامهسازی کاربردی Player در سراسر مؤلفهها/فرایندها با
MediaBrowser/MediaController. - از قابلیتهای گسترشیافته
MediaSessionوMediaControllerAPI استفاده کنید. - قابلیتهای بازپخش را با کنترل دسترسی دقیق تبلیغ کنید.
- با برداشتن
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 (بسته به
android.support.v4.media.*بستههایandroidx.media:media:1.4.3+)
کد مشتری را بااستفاده ازMediaBrowserCompatیاMediaControllerCompatانتقال دهید تا ازandroidx.media3.session.MediaBrowserباandroidx.media3.common.MediaItemاستفاده کنید.
پیشنیازها
مطمئن شوید پروژهتان تحت کنترل منبع است
مطمئن شوید که میتوانید تغییرات اعمالشده توسط ابزارهای انتقال اسکریپتشده را برگردانید. اگر هنوز پروژهتان را تحت کنترل منبع قرار ندادهاید، اکنون زمان خوبی برای شروع آن است. اگر به هر دلیلی نمیخواهید این کار را انجام دهید، قبلاز شروع انتقال، یک نسخه پشتیبان از پروژهتان تهیه کنید.
بهروزرسانی برنامه
توصیه میکنیم پروژهتان را بهروز کنید تا از جدیدترین نسخه کتابخانه ExoPlayer استفاده کند و هرگونه فراخوانی به روشهای منسوخشده را بردارید. اگر قصد دارید از دستورگان برای انتقال استفاده کنید، باید نسخهای را که به آن بهروزرسانی میکنید با نسخهای که توسط دستورگان مدیریت میشود مطابقت دهید.
compileSdkVersion برنامهتان را حداقل به ۳۲ افزایش دهید.
Gradle و افزایه Android Studio Gradle را به نسخه جدیدی ارتقا دهید که با وابستگیهای بهروزشده ذکرشده در بالا کار میکند. برای مثال:
- نسخه افزایه Android Gradle: 7.1.0
- نسخه Gradle: ۷.۴
همه عبارتهای وارد کردن با نویسه عام را که از ستاره (*) استفاده میکنند جایگزین کنید و از عبارتهای وارد کردن کاملاً واجدشرایط استفاده کنید: عبارتهای وارد کردن با نویسه عام را حذف کنید و از 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 Android نوشتهشده در 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، این مراحل دستی را تکمیل کنید:
- بررسی کنید که اسکریپت چگونه کد شما را تغییر داده است: از ابزار diff استفاده کنید و مشکلات احتمالی را برطرف کنید (اگر فکر میکنید اسکریپت مشکل کلی دارد که بدون گذراندن گزینه
-fمعرفی شده است، اشکال را ثبت کنید). - پروژه را بسازید: از
./gradlew clean buildاستفاده کنید یا در «استودیو Android» فایل > همگامسازی پروژه با فایلهای Gradle، سپس ساختن > پاک کردن پروژه، و سپس ساختن > بازساختن پروژه را انتخاب کنید (ساختن خود را در برگه «ساختن - خروجی ساختن» در «استودیو Android» پایش کنید).
مراحل پیگیری توصیهشده:
- موافقت کردن با خطاهای مربوط به استفاده از میاناهای برنامهسازی کاربردی ناپایدار را حل کنید.
- جایگزین کردن فراخوانیهای API منسوخشده: از API جایگزین پیشنهادی استفاده کنید. اشارهگر را روی هشدار در «استودیو Android» نگه دارید و JavaDoc نماد منسوخشده را بررسی کنید تا ببینید بهجای تماس دادهشده از چه چیزی باید استفاده کنید.
- مرتبسازی دستورات وارد کردن: پروژه را در «استودیو Android» باز کنید، سپس روی گره پوشه بسته در نمایشگر پروژه کلیک راست کنید و بهینهسازی وارد کردنها را در بستههایی که حاوی فایلهای منبع تغییریافته هستند انتخاب کنید.
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.11.1"MediaSessionCompatرا باandroidx.media3.session.MediaSessionجایگزین کنید.در سایت کدی که
MediaSessionCompatقدیمی را ایجاد کردهاید، ازandroidx.media3.session.MediaSession.Builderبرای ساختنMediaSessionاستفاده کنید. پخشکننده را ارسال کنید تا سازنده جلسه ساخته شود.کاتلین
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()را پیادهسازی کنید. این میانای برنامهسازی کاربردی روشهای مختلف فعلی و قدیمی را ارائه میدهد که فایلهای رسانهای را به پخشکننده اضافه میکنند تا بهصورت سازگار با نسخههای قدیمی بازپخش شوند. این شامل روشهایMediaController.set/addMediaItems()کنترلکننده Media3 و همچنین روشهایTransportControls.prepareFrom*/playFrom*میانای برنامهسازی کاربردی قدیمی میشود. نمونهای از پیادهسازیonAddMediaItemsرا میتوانید درPlaybackServiceبرنامه نمایشی جلسه پیدا کنید.جلسه رسانه را در سایت کد که در آن جلسه را قبلاز انتقال ازبین بردید، منتشر کنید:
کاتلین
mediaSession?.run { player.release() release() mediaSession = null }
جاوا
if (mediaSession != null) { mediaSession.getPlayer().release(); mediaSession.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 مقدمه خوبی برای 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.11.1"سرویس خود را تغییر دهید تا بهجای
MediaBrowserServiceازMediaLibraryServiceارثبری کند. همانطور که قبلاً گفته شد،MediaLibraryServiceباMediaBrowserServiceقدیمی سازگار است. بنابراین، میانای برنامهسازی کاربردی گستردهتری که سرویس به کارخواهان ارائه میدهد همچنان یکسان است. بنابراین احتمالاً برنامه میتواند بیشتر منطق لازم برای پیادهسازیMediaBrowserServiceرا حفظ کند و آن را برایMediaLibraryServiceجدید تطبیق دهد.تفاوتهای اصلی در مقایسه با
MediaBrowserServiceCompatقدیمی به شرح زیر است:پیادهسازی روشهای چرخه حیات سرویس: روشهایی که باید در خود سرویس لغو شوند عبارتاند از
onCreateوonDestroy، که در آنها برنامه جلسه کتابخانه، پخشکننده، و سایر منابع را اختصاص میدهد یا آزاد میکند. علاوهبر روشهای استاندارد چرخه حیات سرویس، برنامه بایدonGetSession(MediaSession.ControllerInfo)را لغو کند تاMediaLibrarySessionساختهشده درonCreateرا برگرداند.پیادهسازی MediaLibraryService.MediaLibrarySessionCallback: ساختن جلسه به
MediaLibraryService.MediaLibrarySessionCallbackنیاز دارد که روشهای میانای برنامهسازی کاربردی دامنه واقعی را پیادهسازی میکند. بنابراین، بهجای لغو کردن روشهای میانای برنامهسازی کاربردی سرویس قدیمی، روشهایMediaLibrarySession.Callbackرا لغو خواهید کرد.سپس از فراخوانی برگشتی برای ساختن
MediaLibrarySessionاستفاده میشود:کاتلین
mediaLibrarySession = MediaLibrarySession.Builder(context, player, MySessionCallback()).build()
جاوا
mediaLibrarySession = new MediaLibrarySession.Builder(context, player, new MySessionCallback()).build();
میانای برنامهسازی کاربردی کامل MediaLibrarySessionCallback را در اسناد میانای برنامهسازی کاربردی پیدا کنید.
MediaSession.Callback.onAddMediaItems()را پیادهسازی کنید: فراخوانی برگشتیonAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)به روشهای مختلف میانای برنامهسازی کاربردی فعلی و قدیمی که فایلهای رسانهای را برای بازپخش به روش سازگار با نسخه قدیمی به پخشکننده اضافه میکنند، خدمات ارائه میدهد. این شامل روشهایMediaController.set/addMediaItems()کنترلکننده Media3 و همچنین روشهایTransportControls.prepareFrom*/playFrom*میانای برنامهسازی کاربردی قدیمی میشود. نمونهای از پیادهسازی فراخوانی برگشتی را میتوانید درPlaybackServiceبرنامه نمایشی جلسه پیدا کنید.AndroidX Media3 بهجای
MediaBrowserCompat.MediaItemوMediaMetadataCompatازandroidx.media3.common.MediaItemاستفاده میکند. بخشهایی از کد شما که به کلاسهای قدیمی گره خورده است باید بهطور مناسب تغییر کند یا بهجای آن به 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")) 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 برای کنترل بازپخش در پسزمینه، به
کنترل بازپخش در جلسه رسانه
مراجعه کنید.
مراحل بعدی و پاکسازی
بخشهای زیر نحوه رسیدگی به خطاهای lint میانای برنامهسازی کاربردی ناپایدار و میاناهای برنامهسازی کاربردی منسوخشده را پساز تکمیل انتقال اولیه توضیح میدهند.
خطاهای میانای برنامهسازی کاربردی ناپایدار
پساز انتقال به Media3، ممکن است خطاهای lint درباره استفاده از میانای برنامهسازی کاربردی ناپایدار ببینید.
استفاده از این میاناهای برنامهسازی کاربردی ایمن است و خطاهای lint محصول جانبی خطمشی جدید سازگاری دودویی ما است. اگر به سازگاری دودویی دقیق نیاز ندارید،
این خطاها را میتوان با حاشیهنویسی @OptIn بهطور ایمن سرکوب کرد.
پسزمینه
هیچکدام از نسخههای ۱ یا ۲ ExoPlayer سازگاری دودویی دقیقی برای کتابخانه بین نسخههای بعدی ارائه نمیدهند. سطح ExoPlayer API ازنظر طراحی بسیار بزرگ است تا برنامهها بتوانند تقریباً همه جنبههای بازپخش را سفارشیسازی کنند. نسخههای بعدی ExoPlayer گاهیاوقات تغییر نام نمادها یا تغییرات مخرب دیگری را معرفی میکردند (مثلاً روشهای جدید موردنیاز در رابطها). در بیشتر موارد، این خرابیها با معرفی نماد جدید در کنار منسوخ کردن نماد قدیمی برای چند نسخه کاهش یافت تا توسعهدهندگان زمان کافی برای انتقال کاربردهای خود داشته باشند، اما این کار همیشه ممکن نبود.
این تغییرات ناسازگار منجر به دو مشکل برای کاربران کتابخانههای ExoPlayer نسخه ۱ و ۲ شد:
- ارتقا دادن به نسخه ExoPlayer میتواند باعث شود کد دیگر کامپایل نشود.
- برنامهای که هم بهطور مستقیم و هم بااستفاده از کتابخانه واسطه به ExoPlayer وابسته بود، باید اطمینان حاصل میکرد که هر دو وابستگی از یک نسخه باشند، درغیراینصورت ناسازگاریهای دودویی میتوانست منجر به ازکارافتادن زمان اجرا شود.
بهبودهای Media3
Media3 سازگاری دودویی را برای زیرمجموعهای از سطح میانای برنامهسازی کاربردی ارائه میدهد. بخشهایی
که سازگاری دودویی ارائه نمیدهند با @UnstableApi علامتگذاری شدهاند.
برای شفافسازی این تمایز، استفاده از نمادهای ناپایدار میانای برنامهسازی کاربردی
خطای lint ایجاد میکند، مگراینکه با @OptIn حاشیهنویسی شده باشند.
پساز انتقال از ExoPlayer نسخه ۲ به Media3، ممکن است خطاهای lint زیادی در API ناپایدار مشاهده کنید. این ممکن است باعث شود Media3 «کمثباتتر» از ExoPlayer v2 بهنظر برسد. اینطور نیست. بخشهای «ناپایدار» Media3 API همان سطح پایداری را دارند که کل سطح ExoPlayer v2 API دارد، و سازگاری دودویی سطح Media3 API پایدار اصلاً در ExoPlayer v2 دردسترس نیست. تفاوت این است که اکنون خطای lint به شما درباره سطوح مختلف پایداری هشدار میدهد.
رسیدگی به خطاهای lint میانای برنامهسازی کاربردی ناپایدار
برای جزئیات بیشتر درباره نحوه حاشیهنویسی کاربردهای Java و Kotlin از میاناهای برنامهسازی کاربردی ناپایدار با @OptIn، به بخش عیبیابی مربوط به این خطاهای lint مراجعه کنید.
میاناهای برنامهسازی کاربردی منسوخشده
ممکن است متوجه شوید که فراخوانیهای میاناهای برنامهسازی کاربردی منسوخشده در Android Studio خطخوردهاند. توصیه میکنیم این فراخوانیها را با جایگزین مناسب عوض کنید. نشانگر را روی نماد نگه دارید تا JavaDoc را ببینید که میگوید بهجای آن از کدام API استفاده کنید.
نمونههای کد و برنامههای نمایشی
- برنامه نمایشی جلسه AndroidX Media3 (تلفن همراه و WearOS)
- کنشهای سفارشی
- اعلان میانای کاربری سیستم، MediaButton/BT
- کنترل بازپخش «دستیار Google»
- UAMP: Android Media Player (branch media3) (تلفن همراه، AutomotiveOS)
- اعلان واسط کاربری سیستم، MediaButton/BT، ازسرگیری بازپخش
- کنترل بازپخش «دستیار Google»/WearOS
- AutomotiveOS: custom command and sign-in