کنترل پخش را فعال کنید

برای فعال کردن پخش رسانه در اندروید اتو و سیستم عامل اندروید اتوموتیو (AAOS)، با ثبت یک جلسه رسانه و مدیریت متدهای فراخوانی آن، کنترل‌های پخش را پیاده‌سازی کنید. این صفحه نحوه انجام موارد زیر را توضیح می‌دهد:

  • یک شیء MediaSessionCompat را در سرویس مرورگر رسانه خود ثبت کنید.

  • متدهای MediaSessionCompat.Callback را برای پاسخ به درخواست‌های پخش کاربر پیاده‌سازی کنید.

  • پیکربندی اقدامات پخش استاندارد و سفارشی.

  • وضعیت پخش اولیه را برای جلسه رسانه خود تنظیم کنید.

  • آیکون‌هایی برای نشان دادن فرمت صدا اضافه کنید.

  • از آیتم‌های رسانه‌ای که به طور فعال پخش می‌شوند، لینک ایجاد کنید.

اندروید اتو و AAOS دستورات کنترل پخش را از طریق MediaSessionCompat برای سرویس شما ارسال می‌کنند. شما باید یک جلسه (session) ثبت کنید و متدهای فراخوانی مرتبط را پیاده‌سازی کنید.

ثبت نام جلسه رسانه ای

در متد onCreate سرویس مرورگر رسانه خود، یک نمونه از MediaSessionCompat ایجاد کنید، سپس setSessionToken را برای ثبت جلسه رسانه فراخوانی کنید. این قطعه کد نحوه ایجاد و ثبت یک جلسه رسانه را نشان می‌دهد:

کاتلین

override fun onCreate() {
    super.onCreate()
    ...
    // Start a new MediaSession.
    val session = MediaSessionCompat(this, "session tag").apply {
        // Set a callback object that implements MediaSession.Callback
        // to handle play control requests.
        setCallback(MyMediaSessionCallback())
    }
    sessionToken = session.sessionToken
    ...
}

جاوا

public void onCreate() {
    super.onCreate();
    ...
    // Start a new MediaSession.
    MediaSessionCompat session = new MediaSessionCompat(this, "session tag");
    setSessionToken(session.getSessionToken());

    // Set a callback object that implements MediaSession.Callback
    // to handle play control requests.
    session.setCallback(new MyMediaSessionCallback());
    ...
}

وقتی شیء جلسه رسانه را ایجاد می‌کنید، یک شیء فراخوانی تنظیم می‌کنید که برای مدیریت درخواست‌های کنترل پخش استفاده می‌شود. شما این شیء فراخوانی را با ارائه پیاده‌سازی کلاس MediaSessionCompat.Callback برای برنامه خود ایجاد می‌کنید. بخش بعدی نحوه پیاده‌سازی این شیء را مورد بحث قرار می‌دهد.

اجرای دستورات پخش

وقتی کاربری درخواست پخش یک آیتم رسانه‌ای از برنامه شما را می‌دهد، Android Automotive OS و Android Auto از کلاس MediaSessionCompat.Callback از شیء MediaSessionCompat برنامه شما که از سرویس مرورگر رسانه برنامه شما دریافت کرده‌اند، استفاده می‌کنند. وقتی کاربری می‌خواهد پخش محتوا را کنترل کند، مانند مکث پخش یا رفتن به آهنگ بعدی، Android Auto و Android Automotive OS یکی از متدهای شیء callback را فراخوانی می‌کنند.

برای مدیریت پخش محتوا، برنامه شما باید کلاس انتزاعی MediaSessionCompat.Callback را ارث بری کند و متدهایی را که برنامه شما پشتیبانی می‌کند، پیاده‌سازی کند.

هر یک از این متدهای فراخوانی را که برای نوع محتوای ارائه شده توسط برنامه شما منطقی است، پیاده‌سازی کنید:

onPrepare
AAOS این متد را زمانی که منبع رسانه تغییر می‌کند، فراخوانی می‌کند.
onPlay

زمانی که کاربر بدون انتخاب یک مورد خاص، گزینه پخش را انتخاب می‌کند، فراخوانی می‌شود. برنامه شما باید محتوای پیش‌فرض خود را پخش کند یا اگر پخش با onPause متوقف شده باشد، برنامه شما پخش را از سر می‌گیرد.

onPlayFromMediaId

زمانی که کاربر تصمیم به پخش یک آیتم خاص می‌گیرد، فراخوانی می‌شود. این متد، شناسه‌ای را که سرویس مرورگر رسانه شما در سلسله مراتب محتوا به آیتم رسانه اختصاص داده است، دریافت می‌کند.

onPlayFromSearch

زمانی فراخوانی می‌شود که کاربر از طریق یک عبارت جستجو، پخش را انتخاب کند. برنامه باید بر اساس رشته جستجوی ارسال شده، انتخاب مناسبی انجام دهد.

onPause

زمانی که کاربر تصمیم به مکث پخش می‌گیرد، فراخوانی می‌شود.

onSkipToNext

زمانی فراخوانی می‌شود که کاربر تصمیم به رفتن به مورد بعدی بگیرد.

onSkipToPrevious

زمانی فراخوانی می‌شود که کاربر تصمیم به پرش به مورد قبلی بگیرد.

onStop

زمانی که کاربر تصمیم به توقف پخش می‌گیرد، فراخوانی می‌شود. این متدها را در برنامه خود برای ارائه نتیجه انتخاب شده، بازنویسی کنید. اگر هدف یک متد توسط برنامه شما پشتیبانی نمی‌شود، نیازی به پیاده‌سازی آن ندارید. به عنوان مثال، اگر برنامه شما یک پخش زنده مانند پخش ورزشی را پخش می‌کند، نیازی به پیاده‌سازی onSkipToNext ندارید. در عوض، از پیاده‌سازی پیش‌فرض onSkipToNext استفاده کنید.

برنامه شما برای پخش محتوا از طریق بلندگوهای خودرو به هیچ منطق خاصی نیاز ندارد. وقتی برنامه شما درخواستی برای پخش محتوا دریافت می‌کند، صدا را به همان روشی که محتوا از طریق بلندگوهای تلفن یا هدفون کاربر پخش می‌شود، پخش می‌کند. اندروید اتو و AAOS به طور خودکار محتوای صوتی را به سیستم خودرو ارسال می‌کنند تا از طریق بلندگوهای خودرو پخش شود.

برای کسب اطلاعات بیشتر در مورد پخش محتوای صوتی، به نمای کلی Media Player ، نمای کلی برنامه صوتی و نمای کلی ExoPlayer مراجعه کنید.

تنظیم اقدامات پخش استاندارد

اندروید اتو و AAOS کنترل‌های پخش را بر اساس اقداماتی که در شیء PlaybackStateCompat فعال شده‌اند، نمایش می‌دهند. به طور پیش‌فرض، برنامه شما باید از اقدامات زیر پشتیبانی کند:

برنامه شما می‌تواند علاوه بر این، از اقدامات زیر نیز پشتیبانی کند، البته اگر مرتبط با محتوای برنامه باشند:

علاوه بر این، می‌توانید به صورت اختیاری یک صف پخش برای نمایش به کاربر ایجاد کنید. برای انجام این کار، متدهای setQueue و setQueueTitle را فراخوانی کنید، اکشن ACTION_SKIP_TO_QUEUE_ITEM را فعال کنید و فراخوانی onSkipToQueueItem را تعریف کنید.

همچنین، پشتیبانی از آیکون «در حال پخش» را اضافه کنید، که نشانگر چیزی است که در حال پخش است. برای انجام این کار، متد setActiveQueueItemId را فراخوانی کنید و شناسه آیتم در حال پخش در صف را ارسال کنید. هر زمان که صف تغییر کند، باید setActiveQueueItemId به‌روزرسانی کنید.

اندروید اتو و AAOS برای هر اقدام فعال‌شده و همچنین صف پخش، دکمه‌هایی را نمایش می‌دهند. وقتی کاربران روی این دکمه‌ها کلیک می‌کنند، سیستم تابع فراخوانی مربوطه را از MediaSessionCompat.Callback فراخوانی می‌کند.

رزرو فضای استفاده نشده

اندروید اتو و AAOS در رابط کاربری، فضایی را برای اکشن‌های ACTION_SKIP_TO_PREVIOUS و ACTION_SKIP_TO_NEXT رزرو می‌کنند. اگر برنامه شما از یکی از این توابع پشتیبانی نمی‌کند، اندروید اتو و AAOS از این فضا برای نمایش هرگونه اکشن سفارشی که ایجاد می‌کنید استفاده می‌کنند.

اگر نمی‌خواهید آن فضاها را با اقدامات سفارشی پر کنید، می‌توانید آنها را رزرو کنید تا Android Auto و AAOS هر زمان که برنامه شما از عملکرد مربوطه پشتیبانی نمی‌کند، آن فضا را خالی بگذارند.

برای انجام این کار، متد setExtras با یک بسته extras که شامل ثابت‌هایی است که با توابع رزرو شده مطابقت دارند، فراخوانی کنید. SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT معادل ACTION_SKIP_TO_NEXT و SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV معادل ACTION_SKIP_TO_PREVIOUS است. از این ثابت‌ها به عنوان کلید در بسته استفاده کنید و از مقدار بولی true به عنوان مقدار استفاده کنید.

تنظیم وضعیت پخش اولیه

همانطور که Android Auto و AAOS با سرویس مرورگر رسانه شما ارتباط برقرار می‌کنند، جلسه رسانه شما وضعیت پخش محتوا را با استفاده از PlaybackStateCompat اطلاع می‌دهد.

برنامه شما نباید به طور خودکار هنگام اتصال AAOS یا Android Auto به سرویس مرورگر رسانه شما، شروع به پخش موسیقی کند. در عوض، برای ادامه یا شروع پخش بر اساس وضعیت خودرو یا اقدامات کاربر، به Android Auto و AAOS تکیه کنید.

برای انجام این کار، PlaybackStateCompat اولیه‌ی جلسه‌ی رسانه‌ی خود را روی STATE_STOPPED ، STATE_PAUSED ، STATE_NONE یا STATE_ERROR تنظیم کنید.

جلسات رسانه‌ای در اندروید اتو و AAOS فقط در طول مدت رانندگی ادامه دارند، بنابراین کاربران مرتباً این جلسات را شروع و متوقف می‌کنند. برای ایجاد یک تجربه یکپارچه بین رانندگی‌ها، وضعیت جلسه قبلی کاربر را پیگیری کنید تا وقتی برنامه رسانه درخواست از سرگیری دریافت می‌کند، کاربر بتواند به طور خودکار از جایی که متوقف شده بود، ادامه دهد. به عنوان مثال، آخرین مورد رسانه‌ای پخش شده، PlaybackStateCompat و صف پخش.

اضافه کردن اکشن‌های پخش سفارشی

شما می‌توانید اکشن‌های پخش سفارشی را برای نمایش اکشن‌های اضافی که برنامه رسانه‌ای شما پشتیبانی می‌کند، اضافه کنید. اگر فضا اجازه دهد (و شما آن را رزرو نکرده باشید)، اندروید اکشن‌های سفارشی را به کنترل‌های انتقال اضافه می‌کند. در غیر این صورت، اکشن‌های سفارشی در منوی Overflow ظاهر می‌شوند. اندروید اکشن‌های سفارشی را به ترتیبی که شما آنها را به PlaybackStateCompat اضافه می‌کنید، نمایش می‌دهد.

از اکشن‌های سفارشی برای ارائه رفتاری متمایز از اکشن‌های استاندارد استفاده کنید. از آنها برای جایگزینی یا کپی کردن اکشن‌های استاندارد استفاده نکنید.

برای افزودن اکشن‌های سفارشی، از متد addCustomAction در کلاس PlaybackStateCompat.Builder استفاده کنید. این قطعه کد نحوه افزودن یک اکشن سفارشی به "شروع یک کانال رادیویی" را نشان می‌دهد:

کاتلین

val customActionExtras = Bundle()
customActionExtras.putInt(
  androidx.media3.session.MediaConstants.EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT,
  androidx.media3.session.CommandButton.ICON_RADIO)

stateBuilder.addCustomAction(
    PlaybackStateCompat.CustomAction.Builder(
        CUSTOM_ACTION_START_RADIO_FROM_MEDIA,
        resources.getString(R.string.start_radio_from_media),
        startRadioFromMediaIcon // or R.drawable.media3_icon_radio
    ).run {
        setExtras(customActionExtras)
        build()
    }
)

جاوا

Bundle customActionExtras = new Bundle();
customActionExtras.putInt(
  androidx.media3.session.MediaConstants.EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT,
  androidx.media3.session.CommandButton.ICON_RADIO);

stateBuilder.addCustomAction(
    new PlaybackStateCompat.CustomAction.Builder(
        CUSTOM_ACTION_START_RADIO_FROM_MEDIA,
        resources.getString(R.string.start_radio_from_media),
        startRadioFromMediaIcon) // or R.drawable.media3_icon_radio
    .setExtras(customActionExtras)
    .build());

برای مثالی دقیق‌تر از این متد، به متد setCustomAction در برنامه نمونه Universal Android Music Player در GitHub مراجعه کنید. پس از ایجاد اکشن سفارشی خود، جلسه رسانه شما می‌تواند با بازنویسی متد onCustomAction به اکشن‌ها پاسخ دهد.

این قطعه کد نشان می‌دهد که برنامه شما چگونه می‌تواند به اقدام «شروع یک کانال رادیویی» پاسخ دهد:

کاتلین

override fun onCustomAction(action: String, extras: Bundle?) {
    when(action) {
        CUSTOM_ACTION_START_RADIO_FROM_MEDIA -> {
            ...
        }
    }
}

جاوا

@Override
public void onCustomAction(@NonNull String action, Bundle extras) {
    if (CUSTOM_ACTION_START_RADIO_FROM_MEDIA.equals(action)) {
        ...
    }
}

برای کسب اطلاعات بیشتر، به متد onCustomAction در برنامه نمونه Universal Android Music Player در GitHub مراجعه کنید.

ایجاد آیکون برای اقدامات سفارشی

هر اکشن سفارشی که ایجاد می‌کنید به یک آیکون نیاز دارد.

اگر توضیحات آن آیکون با یکی از ثابت‌های CommandButton.ICON_ مطابقت دارد، مقدار صحیح را برای کلید EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT از موارد اضافی اکشن سفارشی تنظیم کنید. در سیستم‌های پشتیبانی‌شده، انجام این کار منبع آیکون ارسالی به CustomAction.Builder را لغو می‌کند و به اجزای سیستم اجازه می‌دهد تا اکشن شما و سایر اکشن‌های پخش را به طور مداوم رندر کنند.

همچنین باید یک منبع آیکون مشخص کنید. برنامه‌های موجود در خودروها می‌توانند روی اندازه‌ها و تراکم‌های مختلف صفحه نمایش اجرا شوند، بنابراین آیکون‌هایی که ارائه می‌دهید باید از نوع vector drawable باشند. از vector drawable برای مقیاس‌بندی دارایی‌ها بدون از دست دادن جزئیات استفاده کنید. vector drawable می‌تواند لبه‌ها و گوشه‌ها را با مرزهای پیکسل در وضوح‌های پایین‌تر تراز کند.

اگر یک اقدام سفارشی دارای وضعیت است (اگر تنظیمات پخش را روشن یا خاموش می‌کند)، برای حالت‌های مختلف، آیکون‌های متفاوتی ارائه دهید تا کاربران هنگام انتخاب اقدام، تغییر را مشاهده کنند.

ارائه سبک‌های آیکون جایگزین برای اقدامات غیرفعال

وقتی یک اقدام سفارشی برای زمینه فعلی در دسترس نیست، نماد اقدام سفارشی را با یک نماد جایگزین که آن اقدام را غیرفعال نشان می‌دهد، جابجا کنید.

نمونه‌هایی از آیکون‌های اکشن سفارشی با استایل متفاوت.
شکل ۱. نمونه‌هایی از آیکون‌های اکشن سفارشی خارج از سبک.

فرمت صوتی را مشخص کنید

برای نشان دادن اینکه رسانه در حال پخش از یک فرمت صوتی خاص استفاده می‌کند، می‌توانید آیکون‌هایی را مشخص کنید که در خودروهایی که از این ویژگی پشتیبانی می‌کنند، رندر می‌شوند. می‌توانید KEY_CONTENT_FORMAT_TINTABLE_LARGE_ICON_URI و KEY_CONTENT_FORMAT_TINTABLE_SMALL_ICON_URI را در بسته extras مربوط به آیتم رسانه در حال پخش (که به MediaSession.setMetadata ارسال شده است) تنظیم کنید. هر دو extras را برای تطبیق با طرح‌بندی‌های مختلف تنظیم کنید.

علاوه بر این، می‌توانید KEY_IMMERSIVE_AUDIO extra را تنظیم کنید تا به تولیدکنندگان اصلی خودرو بگویید که این صدای فراگیر است و آنها باید هنگام تصمیم‌گیری در مورد اعمال جلوه‌های صوتی که ممکن است با محتوای فراگیر تداخل داشته باشند، بسیار مراقب باشند.

شما می‌توانید آیتم رسانه‌ای در حال پخش را طوری تنظیم کنید که زیرنویس، توضیحات یا هر دوی آنها به سایر آیتم‌های رسانه‌ای لینک شوند. این به کاربر اجازه می‌دهد تا به سرعت به موارد مرتبط پرش کند؛ برای مثال، آنها ممکن است به آهنگ‌های دیگر از همان هنرمند یا به قسمت‌های دیگر یک پادکست پرش کنند. اگر خودرو از این ویژگی پشتیبانی کند، کاربران می‌توانند برای مرور آن محتوا روی لینک ضربه بزنند.

برای افزودن لینک‌ها، فراداده‌های KEY_SUBTITLE_LINK_MEDIA_ID (برای پیوند از زیرنویس) یا KEY_DESCRIPTION_LINK_MEDIA_ID (برای پیوند از توضیحات) را پیکربندی کنید. برای جزئیات بیشتر، به مستندات مرجع برای این فیلدهای فراداده مراجعه کنید.