برنامههای رسانهای با استفاده از قالبهای کتابخانه برنامه خودرو میتوانند تجربه مرور و پخش رسانه خود را سفارشی کنند، در حالی که اطمینان حاصل شود که این تجربه برای صفحه نمایش خودرو بهینه شده و حواسپرتی هنگام رانندگی را به حداقل میرساند.
این راهنما فرض میکند که شما از قبل یک برنامه رسانهای دارید که صدا را روی تلفن پخش میکند و برنامه رسانهای شما با معماری برنامه رسانهای اندروید مطابقت دارد. کتابخانه برنامه خودرو به شما این امکان را میدهد که تجربه درون برنامهای را با قالبهایی به جای قالبهایی که با استفاده از ساختار داده ساخت برنامههای رسانهای برای خودروها MediaBrowser ساخته شدهاند، جایگزین کنید. شما هنوز باید یک MediaSession برای کنترلهای پخش و یک MediaBrowserService یا MediaLibraryService که برای توصیهها و سایر تجربیات هوشمند استفاده میشود، ارائه دهید.
پیکربندی مانیفست برنامه شما
علاوه بر مراحل شرح داده شده در استفاده از کتابخانه برنامه اندروید برای خودروها ، موارد زیر برای برنامههای رسانهای قالببندی شده مورد نیاز است:
پشتیبانی از دستهبندی را در مانیفست خود اعلام کنید
برنامه شما باید دسته برنامه ماشین androidx.car.app.category.MEDIA را در فیلتر intent مربوط به 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>
حداقل سطح API برنامه خودرو را تنظیم کنید
برنامههای رسانهای که از MediaPlaybackTemplate استفاده میکنند فقط در CAL API 8 و بالاتر پشتیبانی میشوند، مطمئن شوید که حداقل Car App API level شما روی 8 تنظیم شده باشد.
<application ...>
...
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="8"/>
...
</application>
یک نماد انتساب ارائه دهید
حتماً برای برنامههای رسانهای ساخته شده با استفاده از کتابخانه برنامه خودرو، یک نماد انتساب اضافه کنید.
اعلام پشتیبانی از اندروید اتو
مطمئن شوید که موارد زیر در مانیفست برنامه شما گنجانده شده است:
<application>
...
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
سپس، تعریف قالب را به automotive_app_desc.xml در xml resources خود اضافه کنید. باید به شکل زیر باشد:
<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
<uses name="media"/>
<uses name="template"/>
</automotiveApp>
اعلام پشتیبانی از سیستم عامل اندروید اتوموبیل
دو روش مختلف برای توزیع یک برنامه رسانهای با قابلیت Car App Library در سیستم عامل Android Automotive وجود دارد: به عنوان یک APK واحد یا به عنوان دو APK جداگانه. اگر یک APK واحد توزیع کنید، از خودروهایی که برای سیستم عامل Android Automotive با میزبان Car App Library فعال هستند پشتیبانی میکند و در غیر این صورت، حتی برای نسخههای قدیمیتر اندروید (Android 10 - Android 13) به یک برنامه MediaBrowserService یا MediaLibraryService برمیگردد. اگر تصمیم به توزیع دو APK جداگانه دارید، میتوانید راحتتر افزونههای جدید را به نسخه Car App Library بهروزرسانی کنید بدون اینکه نگران تأثیرگذاری بر نسخه MediaBrowserService یا MediaLibraryService برنامه خود باشید.
توزیع یک APK واحد
هنگام توزیع یک APK واحد برای کتابخانه برنامه خودرو و نسخههای MediaBrowserService یا MediaLibraryService برنامه شما، تنظیم "" بسیار مهم است.android:required="false" .
<uses-feature android:name="android.software.car.templates_host.media" android:required="false"/>
در مرحله بعد، دستورالعملهای کتابخانه Car App برای AAOS را دنبال کنید و یک CarAppActivity قابل راهاندازی (یا activity trampoline) معرفی کنید. شما باید activity را در manifest روی android:enabled="false" تنظیم کنید. در مرحله بعد، یک تگ metadata به اعلان MediaBrowserService اضافه کنید که نشاندهنده کامپوننت CarAppActivity به عنوان جایگزین باشد. به مثال manifest زیر توجه کنید:
<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>
توزیع بازی
فایل APK شما به همراه کتابخانه اپلیکیشن خودرو و MediaBrowserService یا MediaLibraryService باید با کد نسخه بالاتر و minSdk که اندروید ۱۴ (۳۴) را هدف قرار میدهد، فعال شود.
توزیع با دو APK
برای توزیع دو APK جداگانه، یکی با استفاده از Car App Library و دیگری با استفاده از MediaBrowserService یا MediaLibraryService ، این مراحل را دنبال کنید تا مطمئن شوید که قابلیتهای صحیح خودرو به درستی هدف قرار گرفتهاند.
هنگام ایجاد یک APK جداگانه برای نسخه Car App Library برنامه خود، باید android.software.car.templates_host.media را روی android:required=true تنظیم کنید. این تضمین میکند که برنامه فقط روی نسخههای سیستم عامل Android Automotive که دارای گواهی پشتیبانی از میزبان Car App Library هستند، توزیع میشود.
<uses-feature android:name="android.software.car.templates_host.media" android:required="true"/>
گذشته از استفاده از android.software.car.templates_host.media و تنظیم آن روی android:required=true در بالا، این مراحل را برای فعال کردن سیستم عامل اندروید خودرو برای فعالیت کتابخانه برنامه خودرو قابل راهاندازی خود دنبال کنید.
توزیع بازی
فایل APK که از کتابخانه برنامه خودرو استفاده میکند، باید در مسیر اختصاصی سیستم عامل خودرو توزیع شود.
پشتیبانی از اقدامات صوتی
برنامه خود را با قابلیت صوتی فعال کنید تا کاربران بتوانند اقدامات رایج را بدون دخالت دست انجام دهند. برای دستورالعملهای دقیقتر پیادهسازی، به پشتیبانی از اقدامات صوتی برای رسانهها مراجعه کنید. با یک برنامه رسانهای قالببندیشده، اگر یک فرمان صوتی دریافت کنید، نیازی به بهروزرسانی MediaBrowserService یا MediaLibraryService با نتایج جستجو ندارید. در عوض، میتوانید یک اقدام را در الگوی پخش رسانه خود اضافه کنید تا به کاربر اجازه دهید محتوای بیشتری را بر اساس آن پخش یا جستجوی جستجو پیدا کند. پشتیبانی از دستورات صوتی برای رعایت دستورالعمل کیفیت VC-1 الزامی است.
الگوی پخش خود را ایجاد کنید
قالب MediaPlaybackTemplate اطلاعات پخش رسانه را در کتابخانه برنامه خودرو (Car App Library) نمایش میدهد. این قالب امکان تنظیم یک سرصفحه (header) با عنوان و اقدامات قابل تنظیم را فراهم میکند، در حالی که اطلاعات رسانه و کنترلهای پخش توسط میزبان و بر اساس وضعیت 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 استفاده میکنند و از PlatformToken به جای MediaSessionCompat.Token استاندارد استفاده میکنند، باید یک SessionCommand سفارشی در MediaLibrarySession.Callback خود پیادهسازی کنید که توکن پلتفرم اصلی session را برمیگرداند: session.platformToken . در CarAppService خود این دستور سفارشی را به session ارسال کنید. پس از دریافت توکن پلتفرم، آن را با استفاده از MediaSessionCompat.Token.fromToken(platformToken) تبدیل کنید و این توکن compat را به کتابخانه Car App در .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();
کامپوننتها و ویژگیهای کتابخانه اپلیکیشن خودرو ۱.۹
نسخه ۱.۹ API کتابخانه اپلیکیشن خودرو، کامپوننتهای سفارشیسازیشدهای را برای قابلیتهای منحصربهفرد مرور، مانند تراشهها ، نوارهای پیشرفت ، موارد فشرده ، سربرگ تعاملی و گسترده ، بخشهای ویژه و بنرها، معرفی میکند.

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

شکل ۴: دو صفحه مرور رسانه شامل Expanded Header ، Spotlight Sections و Progress Bars
برای جزئیات بیشتر در مورد نحوه طراحی رابط کاربری برنامه رسانهای خود با استفاده از این الگوها، به برنامههای رسانهای مراجعه کنید.
پیمایش به کنترلهای پخش
هنگام مرور رسانهها، مهم است که کاربر بتواند به سرعت و با حداقل حواسپرتی به MediaPlaybackTemplate دسترسی پیدا کند. برای برآورده کردن الزام کیفیت MFT-1 ، برنامه شما باید راهی برای دسترسی به MediaPlaybackTemplate از تمام صفحات مرور رسانه داشته باشد.
اگر از SectionedItemTemplate استفاده میکنید، میتوانید با اضافه کردن یک دکمهی عملیاتی که شما را به صفحهی پخش رسانه هدایت میکند، به این هدف دست یابید. از اکشن استاندارد Car App Library Action.MEDIA_PLAYBACK استفاده کنید. یک برنامهی رسانهای این اکشن را به عنوان یک پنل کنترل Minimized نمایش میدهد که در صورت استفاده از Car App Library API 1.9 یا بالاتر، برای برآورده کردن الزامات کیفیت MFT-1 مورد نیاز است. برای سایر قالبها، یک اکشن هدر راه دیگری برای دستیابی به این هدف است.
مدیریت اهداف پخش رسانه سیستم
لازم است هنگام اجرای برنامه از یک سطح پخش رسانهای سیستمی، مانند کارت رسانه، کاربر را به MediaPlaybackTemplate هدایت کند. ما نیاز داریم که برنامههای رسانهای این Intent Action مدیریت کنند تا تجربهای روان برای کاربران فراهم شود.
اکشن androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK را به intent-filter کامپوننت Car App Library خود (یا CarAppActivity یا trampoline Activity ) اضافه کنید.
مطمئن شوید که 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() برای تجزیهی intent ورودی، override کنید. اگر اکشن intent ورودی با 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));
}
}
اگر از یک اکتیویتی ترامپولین استفاده میکنید، اکشن intent را در onCreate() بررسی کنید. این اکشن را قبل از فراخوانی finish() به intent مربوط به ساخت 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();
}
}