ساختن برنامه رسانه الگوبرداری‌شده

برنامه‌های رسانه‌ای الگو در مرحله بتا است
درحال‌حاضر، هرکسی می‌تواند برنامه‌های رسانه‌ای مبتنی بر الگو را در دسته‌های هدف آزمایشی داخلی و آزمایشی بسته در «فروشگاه Google Play» منتشر کند. انتشار در دسته‌های هدف باز و دسته‌های هدف تولید در تاریخ دیگری مجاز خواهد بود.

برنامه‌های رسانه‌ای که از الگوهای «کتابخانه برنامه‌های ماشین» استفاده می‌کنند می‌توانند تجربه مرور و بازپخش رسانه خود را سفارشی‌سازی کنند و درعین‌حال مطمئن شوند که این تجربه برای صفحه‌نمایش خودرو بهینه‌سازی شده است و حواس‌پرتی‌ها را درحین رانندگی به‌حداقل می‌رساند.

این راهنما فرض می‌کند که ازقبل برنامه رسانه‌ای دارید که صدا را در تلفن پخش می‌کند و برنامه رسانه شما با معماری برنامه رسانه Android مطابقت دارد. «کتابخانه برنامه خودرو» به شما امکان می‌دهد تجربه درون‌برنامه را با الگوها جایگزین کنید، به‌جای الگوهایی که بااستفاده از ساختار داده ساختن برنامه‌های رسانه برای خودرو MediaBrowser ساخته شده‌اند. همچنان باید MediaSession برای کنترل‌های بازپخش، و MediaBrowserService یا MediaLibraryService ارائه دهید که برای توصیه‌ها و دیگر تجربه‌های هوشمند استفاده می‌شود.

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

پیکربندی مانیفست برنامه

علاوه‌بر مراحل شرح‌داده‌شده در استفاده از کتابخانه برنامه Android برای ماشین‌ها، موارد زیر برای برنامه‌های رسانه‌ای الگودار الزامی است:

اعلام پشتیبانی از دسته در مانیفست

برنامه شما باید androidx.car.app.category.MEDIA دسته برنامه خودرو را در فیلتر قصد CarAppService خود اعلام کند.

<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.MEDIA"/>
      </intent-filter>
    </service>
    ...
<application>

برای دسترسی به MediaPlaybackTemplate، برنامه‌تان باید اجازه androidx.car.app.MEDIA_TEMPLATES را نیز در فایل مانیفست خود اعلام کند:

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.MEDIA_TEMPLATES"/>
  ...
</manifest>

تنظیم حداقل سطح ای‌پی‌آی برنامه خودرو

برنامه‌های رسانه‌ای که از MediaPlaybackTemplate استفاده می‌کنند فقط در CAL API 8 و نسخه‌های بالاتر پشتیبانی می‌شوند، مطمئن شوید حداقل Car App API level روی ۸ تنظیم شده باشد.

<application ...>
  ...
  <meta-data
    android:name="androidx.car.app.minCarApiLevel"
    android:value="8"/>
  ...
</application>

نماد ارجاع ارائه دهید

حتماً برای برنامه‌های رسانه‌ای ساخته‌شده بااستفاده از «کتابخانه برنامه ماشین»، نماد ارجاع اضافه کنید.

اعلام پشتیبانی Android Auto

مطمئن شوید موارد زیر در مانیفست برنامه‌تان گنجانده شده باشد:

<application>
  ...
  <meta-data android:name="com.google.android.gms.car.application"
      android:resource="@xml/automotive_app_desc"/>
  ...
</application>

سپس، اظهارنامه الگو را به automotive_app_desc.xml در منابع xml خود اضافه کنید. باید به‌صورت زیر باشد:

<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
 <uses name="media"/>
 <uses name="template"/>
</automotiveApp>

اعلام پشتیبانی از «سیستم عامل Android Automotive»

به دو روش مختلف می‌توانید برنامه رسانه فعال‌شده Car App Library را در «سیستم‌عامل Android Automotive» توزیع کنید: به‌صورت یک APK واحد یا به‌صورت دو APK جداگانه. اگر یک فایل APK تکی توزیع کنید، این فایل از خودروهایی که برای «سیستم عامل Android Automotive» با میزبان «کتابخانه برنامه خودرو» فعال شده‌اند پشتیبانی می‌کند و درغیراین‌صورت به برنامه MediaBrowserService یا MediaLibraryService برمی‌گردد، حتی برای نسخه‌های قدیمی‌تر Android (‏Android 10 تا Android 13). اگر تصمیم بگیرید دو فایل APK جداگانه توزیع کنید، می‌توانید موارد جدید اضافه‌شده به نسخه Car App Library را بدون نگرانی از تأثیرگذاری بر نسخه MediaBrowserService یا MediaLibraryService برنامه‌تان به‌روز کنید.

توزیع یک APK

هنگام توزیع یک APK برای Car App Library و نسخه‌های MediaBrowserService یا MediaLibraryService برنامه‌تان، بسیار مهم است که android.software.car.templates_host.media را روی android:required="false" تنظیم کنید.

<uses-feature android:name="android.software.car.templates_host.media" android:required="false"/>

سپس، دستورالعمل‌های «کتابخانه برنامه خودرو» برای AAOS را دنبال کنید و CarAppActivity قابل‌راه‌اندازی (یا فعالیت ترامپولین) را معرفی کنید. باید فعالیت را در مانیفست روی android:enabled="false"‎ تنظیم کنید. سپس، برچسب فراداده‌ای به اعلان MediaBrowserService اضافه کنید که نشان دهد مؤلفه CarAppActivity جایگزین است. مانیفست نمونه زیر را ببینید:

<service android:name=".media.MyMediaService"
    android:exported="true"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
    </intent-filter>

    <!-- Link to Car App Library Activity -->
    <meta-data
        android:name="androidx.car.app.media.CalMediaActivityComponent"
        android:value="com.example.mediaapp.LaunchableTrampoline"/>
</service>

<activity
    android:name=".LaunchableTrampoline"
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:launchMode="singleTask"
    android:label="@string/app_name_cal"
    android:enabled="false"> <!-- Set to false -->

    <meta-data android:name="distractionOptimized" android:value="true" />

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

توزیع Play

فایل APK شما با «کتابخانه برنامه‌های ماشین» و MediaBrowserService یا MediaLibraryService باید با کد نسخه بالاتر و minSdk که Android 14‏ (34) را هدف قرار می‌دهد فعال شود.

توزیع با دو APK

برای توزیع دو APK جداگانه، یکی بااستفاده از «کتابخانه برنامه‌های ماشین» و دیگری بااستفاده از MediaBrowserService یا MediaLibraryService، این مراحل را دنبال کنید تا مطمئن شوید قابلیت‌های صحیح خودرو به‌درستی هدف‌یابی شده‌اند.

هنگام ایجاد APK جداگانه برای نسخه «کتابخانه برنامه‌های ماشین» برنامه‌تان، باید android.software.car.templates_host.media را روی android:required=true تنظیم کنید. این کار تضمین می‌کند که برنامه فقط در ساخت‌های «سیستم عامل Android Automotive» که با پشتیبانی از میزبان «کتابخانه برنامه خودرو» تأیید شده‌اند توزیع شود.

<uses-feature android:name="android.software.car.templates_host.media" android:required="true"/>

علاوه‌بر استفاده از android.software.car.templates_host.media و تنظیم آن روی android:required=true، این مراحل را برای فعال کردن سیستم عامل Android Automotive برای فعالیت قابل‌راه‌اندازی «کتابخانه برنامه خودرو» دنبال کنید.

توزیع Play

فایل APK که از «کتابخانه برنامه خودرو» استفاده می‌کند باید در دسته هدف اختصاصی Automotive OS توزیع شود.

پشتیبانی از کنش‌های گفتاری

برنامه‌تان را صوتی کنید تا کاربران بتوانند کنش‌های رایج را در حالت دست‌آزاد انجام دهند. برای دستورالعمل‌های دقیق‌تر پیاده‌سازی، به پشتیبانی از کنش‌های گفتاری برای رسانه مراجعه کنید. با برنامه رسانه قالب‌بندی‌شده، اگر فرمان صوتی دریافت کنید، نیازی نیست MediaBrowserService یا MediaLibraryService خود را با نتایج جستجو به‌روز کنید. درعوض، کنشی به الگوی بازپخش رسانه اضافه کنید تا کاربر بتواند براساس آن پرسمان جستجو یا پخش، محتوای بیشتری پیدا کند. پشتیبانی از فرمان‌های صوتی برای برآورده کردن دستورالعمل کیفیت VC-1 الزامی است.

ایجاد کردن «الگوی بازپخش»

MediaPlaybackTemplate اطلاعات بازپخش رسانه را در برنامه رسانه «کتابخانه برنامه خودرو» شما نمایش می‌دهد. این الگو امکان تنظیم سرصفحه با عنوان و کنش‌های سفارشی‌سازی‌شدنی را فراهم می‌کند، درحالی‌که اطلاعات رسانه و کنترل‌های بازپخش توسط میزبان براساس وضعیت MediaSession برنامه شما پر می‌شود.

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

شکل ۱: MediaPlaybackTemplate با کنش سرصفحه برای باز کردن صف در امتداد بالا.

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

val playbackTemplate = MediaPlaybackTemplate.Builder()
      .setHeader(
        Header.Builder()
          .setStartHeaderAction(Action.BACK)
          .addEndHeaderAction(
                Action.Builder()
                  .setTitle(model.context.getString(R.string.queue_button_title))
                  .setIcon(
                    CarIcon.Builder(
                        IconCompat.createWithResource(
                          model.context,
                          R.drawable.gs_queue_music_vd_theme_24,
                        ))
                      .build())
                  .setOnClickListener(showQueueScreen())
                  .build())
          .setTitle(model.context.getString(R.string.media_playback_view_title))
          .build())
      .build()

وقتی از MediaPlaybackTemplate استفاده می‌کنید، یک کد MediaSession را بااستفاده از MediaPlaybackManager در CarAppService ثبت کنید. درصورت عدم انجام این کار، هنگام ارسال MediaPlaybackTemplate به میزبان، خطا نمایش داده می‌شود.

import androidx.car.app.media.MediaPlaybackManager
…

override fun onCreateSession(sessionInfo: SessionInfo): Session {
    return object : Session() {
        …

        init {
          lifecycle.addObserver(
            LifecycleEventObserver { _, event ->
              if (event == ON_CREATE) {
                val token = ... // MediaSessionCompat.Token
                (carContext.getCarService(CarContext.MEDIA_PLAYBACK_SERVICE) as MediaPlaybackManager)
                  .registerMediaPlaybackToken(token)
              }
              ...
            }
          )
        }
    }
}

‫.registerMediaPlaybackToken برای نمایش اطلاعات و کنترل‌های بازپخش رسانه در Android Auto ضروری است. این موضوع برای میزبان نیز مهم است تا اعلان‌های خاص رسانه ایجاد کند.

برای برنامه‌هایی که از کتابخانه Media3 استفاده می‌کنند و به‌جای MediaSessionCompat.Token استاندارد از PlatformToken استفاده می‌کنند، باید SessionCommand سفارشی را در MediaLibrarySession.Callback خود پیاده‌سازی کنید که کد پلاتفرم اصلی جلسه را برمی‌گرداند: session.platformToken. در CarAppService این فرمان سفارشی را به جلسه ارسال کنید. پس‌از دریافت کردن نشان‌واره پلاتفرم، آن را بااستفاده از MediaSessionCompat.Token.fromToken(platformToken) تبدیل کنید و این نشان‌واره سازگار را به «کتابخانه برنامه خودرو» در .registerMediaPlaybackToken() ارسال کنید.

سازمان‌دهی رسانه بااستفاده از الگوها

برای سازمان‌دهی رسانه‌ها برای مرور، مثل آهنگ‌ها یا آلبوم‌ها، توصیه می‌کنیم از SectionedItemTemplate استفاده کنید، که به شما امکان می‌دهد از GridSection و RowSection با هم استفاده کنید تا طرح‌بندی‌هایی ایجاد کنید که فهرست‌های تصاویر و موارد نوشتاری را ترکیب می‌کنند.

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

شکل ۲: SectionedItemTemplate حاوی RowSection و به‌دنبال آن GridSection

استفاده از SectionedItemTemplate در TabTemplate

یکی از روش‌های راحت برای دسته‌بندی رسانه در برنامه، استفاده از SectionedItemTemplate در TabTemplate است.

val template =
      SectionedItemTemplate.Builder()...build();
val tabTemplate =
      TabTemplate.Builder(tabCallback)
          .setTabContents(TabContents.Builder(template).build)
          .setHeaderAction(Action.APP_ICON)
          …
          .build();

ویژگی‌ها و مؤلفه‌های نسخه ۱.۹ «کتابخانه برنامه‌های خودرو»

Car App Library API نسخه ۱.۹ مؤلفه‌های سفارشی‌شده‌ای را برای قابلیت‌های مرور منحصربه‌فرد معرفی می‌کند، مانند تراشه‌ها، نوار پیشرفت، موارد فشرده، سرصفحه تعاملی و گسترده، بخش‌های Spotlight، و برنماها.

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

شکل ۳: SectionedItemTemplate حاوی Chips، Condensed Items، Interactive Header، Grid Items، و Minimized Control Panel

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

شکل ۴: دو صفحه مرور رسانه با Expanded Header، Spotlight Sections، و Progress Bars

برای جزئیات بیشتر درباره نحوه طراحی میانای کاربر برنامه رسانه بااستفاده از این الگوها، برنامه‌های رسانه را ببینید.

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

اگر از SectionedItemTemplate استفاده می‌کنید، می‌توانید این کار را با افزودن دکمه کنشی انجام دهید که شما را به صفحه بازپخش رسانه هدایت می‌کند. از کنش استاندارد Action.MEDIA_PLAYBACK «کتابخانه برنامه خودرو» استفاده کنید. برنامه رسانه این کنش را به‌صورت پانل کنترل کوچک‌شده نشان می‌دهد، که برای برآورده کردن الزامات کیفی MFT-1 لازم است اگر از Car App Library API نسخه ۱.۹ یا بالاتر استفاده می‌کنید. برای الگوهای دیگر، کنش سرصفحه روش دیگری برای دستیابی به این هدف است.

مدیریت هدف‌های بازپخش رسانه سیستم

وقتی برنامه‌ای از سطح رسانه درحال پخش سیستم (مثلاً کارت رسانه) راه‌اندازی می‌شود، لازم است کاربر به MediaPlaybackTemplate هدایت شود. ما از برنامه‌های رسانه‌ای می‌خواهیم که این Intent Action را مدیریت کنند تا تجربه‌ای یکپارچه برای کاربران فراهم شود.

کنش androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK را به فیلتر هدف مؤلفه «کتابخانه برنامه‌های» خودرو (CarAppActivity یا ترامپولین Activity) اضافه کنید.

مطمئن شوید فعالیتتان از launchMode singleTask یا singleTop استفاده می‌کند تا onNewIntent() فراخوانده شود.

<activity
    android:name=".LaunchableTrampoline"
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:launchMode="singleTask"
    android:label="@string/app_name_cal"
    android:enabled="false">

    <meta-data android:name="distractionOptimized" android:value="true" />

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

در کلاس Session، onNewIntent() را لغو کنید تا قصد ورودی تجزیه شود. اگر کنش هدف ورودی با SHOW_MEDIA_PLAYBACK مطابقت دارد، کاربر را به صفحه «درحال پخش» خود هدایت کنید.

@Override
public void onNewIntent(@NonNull Intent intent) {
    super.onNewIntent(intent);
    if (SHOW_MEDIA_PLAYBACK.equals(intent.getAction())) {
        ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
        // Avoid redundant navigation if already on the playing screen
        if (screenManager.getTop() instanceof MyMediaPlayScreen) {
            return;
        }
        screenManager.push(MyMediaPlayScreen.createScreenFromPlaying(
                getCarContext(), mMediaSessionController));
    }
}

اگر از فعالیت جَستانه استفاده می‌کنید، کنش هدف را در onCreate() بررسی کنید. این کنش را قبل‌از فراخوانی finish() به قصد ایجاد CarAppActivity ارسال کنید.

public class LaunchableTrampoline extends AppCompatActivity {
    private static final String SHOW_MEDIA_PLAYBACK = "androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent receivedIntent = getIntent();
        String action;

        if (SHOW_MEDIA_PLAYBACK.equals(receivedIntent.getAction())) {
            action = SHOW_MEDIA_PLAYBACK;
        } else {
            action = Intent.ACTION_MAIN;
        }

        Intent intent = new Intent(action);
        intent.setClassName(getPackageName(), "androidx.car.app.activity.CarAppActivity");
        startActivity(intent);
        finish();
    }
}