使用車輛專用應用程式程式庫範本的媒體應用程式,可以自訂媒體瀏覽和播放體驗,同時確保體驗已針對車輛螢幕最佳化,並盡量減少行車時的干擾。
本指南假設您已經有媒體應用程式,可以在手機上播放音訊,且符合 Android 媒體應用程式架構。車輛應用程式程式庫可讓您使用範本取代應用程式內體驗,而非使用「打造車用媒體應用程式」MediaBrowser資料結構建構的體驗。您仍須提供 MediaSession 做為播放控制項,以及 MediaBrowserService 或 MediaLibraryService,用於推薦內容和其他智慧體驗。
設定應用程式的資訊清單
除了「使用車輛專用 Android App Library」一文所述步驟外,範本媒體應用程式還須符合下列規定:
在資訊清單中宣告類別支援
您的應用程式必須在 CarAppService 的意圖篩選器中宣告 androidx.car.app.category.MEDIA 車用應用程式類別:
<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>
提供出處圖示
使用車輛應用程式程式庫建構媒體應用程式時,請務必新增出處圖示。
宣告 Android Auto 支援
請確認應用程式資訊清單中包含下列項目:
<application>
...
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
然後在 XML 資源的 automotive_app_desc.xml 中加入 範本宣告。畫面應如下所示:
<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
<uses name="media"/>
<uses name="template"/>
</automotiveApp>
宣告支援 Android Automotive OS
您可以在 Android Automotive OS 上,以兩種不同方式發布啟用 Car App Library 的媒體應用程式:單一 APK 或兩個獨立 APK。如果您發布單一 APK,該 APK 將支援已啟用 Android Automotive OS 的車輛,並使用 Car App Library 主機,如果不是,則會回溯至 MediaBrowserService 或 MediaLibraryService 應用程式,即使是舊版 Android (Android 10 至 Android 13) 也是如此。如果您選擇發布兩個不同的 APK,就能更輕鬆地更新 Car App Library 版本的新增內容,而不必擔心影響應用程式的 MediaBrowserService 或 MediaLibraryService 版本。
發布單一 APK
為應用程式的 Car App Library 和 MediaBrowserService 或 MediaLibraryService 版本發布單一 APK 時,請務必將「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 應啟用 Car App Library 和 MediaBrowserService
或 MediaLibraryService,並使用較高的版本代碼和 minSdk,指定 Android 14 (34)。
使用兩個 APK 發布
如要發布兩個不同的 APK,一個使用 Car App Library,另一個使用 MediaBrowserService 或 MediaLibraryService,請按照下列步驟操作,確保正確指定車輛功能。
為應用程式的 Car App Library 版本建立個別 APK 時,您必須將 android.software.car.templates_host.media 設為 android:required=true。這樣一來,應用程式只會發布到已通過認證,且支援 Car App Library 主機的 Android Automotive OS 版本。
<uses-feature android:name="android.software.car.templates_host.media" android:required="true"/>
除了使用 android.software.car.templates_host.media 並將其設為上述 android:required=true 之外,請按照下列步驟為可啟動的 Car App Library 活動啟用 Android Automotive OS。
Play Distribution
使用 Car App Library 的 APK 應透過 Automotive OS 專屬測試群組發布。
支援語音指令
為應用程式啟用語音功能,讓使用者不需動手即可完成常見動作。如需更詳細的實作說明,請參閱「支援媒體的語音動作」。使用範本化媒體應用程式時,如果收到語音指令,就不必使用搜尋結果更新 MediaBrowserService 或 MediaLibraryService。建議您改為在媒體播放範本中新增動作,讓使用者根據播放內容或搜尋查詢尋找更多內容。支援語音指令是符合VC-1品質規範的必要條件。
建立播放範本
MediaPlaybackTemplate 會在車輛專用 Cars App Library 媒體應用程式中顯示媒體播放資訊。這個範本可讓您設定含有標題和可自訂動作的標題,而主機會根據應用程式 MediaSession 的狀態填入媒體資訊和播放控制項。
圖 1:
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 時,請使用 CarAppService 中的 MediaPlaybackManager 註冊 MediaSession 權杖。否則,系統會在將 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),您需要在 MediaLibrarySession.Callback 中實作自訂 SessionCommand,傳回工作階段的基礎平台權杖:session.platformToken。在 CarAppService 中,將這項自訂指令傳送至工作階段。收到平台權杖後,請使用 MediaSessionCompat.Token.fromToken(platformToken) 轉換權杖,然後在 .registerMediaPlaybackToken() 中將這個相容性權杖傳遞至 Car App Library。
使用範本整理媒體
如要整理歌曲或專輯等媒體以供瀏覽,建議使用 SectionedItemTemplate,因為這個函式可讓您同時使用 GridSection 和 RowSection,建立混合圖片和文字項目清單的版面配置。
圖 2:包含 RowSection 的 SectionedItemTemplate,後面接著 GridSection
在 TabTemplate 內使用 SectionedItemTemplate
在應用程式中分類媒體的其中一個便利方法,是在 TabTemplate 內使用 SectionedItemTemplate。
val template =
SectionedItemTemplate.Builder()...build();
val tabTemplate =
TabTemplate.Builder(tabCallback)
.setTabContents(TabContents.Builder(template).build)
.setHeaderAction(Action.APP_ICON)
…
.build();
車用應用程式程式庫 1.9 的元件和功能
Car App Library API 1.9 版推出自訂元件,提供獨特的瀏覽功能,例如資訊方塊、進度列、精簡項目、互動式展開標題、精選內容區塊和橫幅。
圖 3:包含 Chips、Condensed Items、Interactive Header、Grid Items 和 Minimized Control Panel 的 SectionedItemTemplate
圖 4:兩個媒體瀏覽畫面,分別顯示 Expanded Header、Spotlight Sections 和 Progress Bars
如要進一步瞭解如何運用這些範本設計媒體應用程式的使用者介面,請參閱「媒體應用程式」。
前往播放控制項
瀏覽媒體時,使用者應能快速前往 MediaPlaybackTemplate,且干擾程度越低越好。為符合MFT-1品質規定,應用程式必須提供從所有媒體瀏覽畫面存取 MediaPlaybackTemplate 的方式。
如果您使用 SectionedItemTemplate,可以新增動作按鈕,將您導向媒體播放畫面。使用標準的 Car App Library Action.MEDIA_PLAYBACK 動作。媒體應用程式會將這項動作顯示為縮小控制面板。如果您使用 Car App Library API 1.9 以上版本,就必須符合MFT-1品質規定。如果是其他範本,則可透過標頭動作達成這個目標。
處理系統媒體播放意圖
當應用程式從播放媒體的系統介面 (例如媒體資訊卡) 啟動時,必須將使用者導向 MediaPlaybackTemplate。為提供流暢的使用者體驗,媒體應用程式必須處理這項 Intent Action。
將 androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK 動作新增至 Car App Library 元件的 intent-filter (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();
}
}