Aplikacje do multimediów korzystające z szablonów biblioteki aplikacji do samochodu mogą dostosowywać sposób przeglądania i odtwarzania multimediów, zapewniając jednocześnie optymalizację pod kątem ekranów samochodowych i minimalizując rozpraszanie uwagi podczas jazdy.
W tym przewodniku założyliśmy, że masz już aplikację do multimediów, która odtwarza dźwięk na telefonie
i że jest ona zgodna z architekturą aplikacji do multimediów na Androida. Biblioteka aplikacji do samochodu umożliwia zastąpienie szablonami funkcji w aplikacji, które zostały utworzone za pomocą struktury danych Build media apps for cars
MediaBrowser. Nadal musisz udostępniać MediaSession do sterowania odtwarzaniem oraz MediaBrowserService lub MediaLibraryService, które są używane do rekomendacji i innych inteligentnych funkcji.
Konfigurowanie pliku manifestu aplikacji
Oprócz czynności opisanych w artykule Korzystanie z biblioteki aplikacji Android do samochodu, aplikacje do multimediów oparte na szablonach muszą spełniać te wymagania:
Deklarowanie obsługi kategorii w pliku manifestu
Aplikacja musi zadeklarować androidx.car.app.category.MEDIA
kategorię aplikacji do samochodu w filtrze intencji usługi 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>
Aby uzyskać dostęp do MediaPlaybackTemplate, aplikacja musi też
zadeklarować uprawnienie androidx.car.app.MEDIA_TEMPLATES w pliku
manifestu:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.MEDIA_TEMPLATES"/>
...
</manifest>
Ustawianie minimalnego poziomu interfejsu API aplikacji do samochodu
Aplikacje do multimediów korzystające z MediaPlaybackTemplate są obsługiwane tylko w CAL API 8 i
nowszych. Upewnij się, że minimalny Car App API level jest ustawiony na 8.
<application ...>
...
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="8"/>
...
</application>
Podawanie ikony źródła
Pamiętaj, aby dodać ikonę źródła w przypadku aplikacji do multimediów utworzonych za pomocą biblioteki aplikacji do samochodu.
Deklarowanie obsługi Androida Auto
Upewnij się, że w pliku manifestu aplikacji znajdują się te elementy:
<application>
...
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
Następnie dodaj deklarację template do pliku automotive_app_desc.xml w zasobach XML. Powinno to wyglądać tak:
<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
<uses name="media"/>
<uses name="template"/>
</automotiveApp>
Deklarowanie obsługi systemu operacyjnego Android Automotive
Aplikację do multimediów korzystającą z biblioteki aplikacji do samochodu możesz rozpowszechniać w systemie operacyjnym Android Automotive na 2 sposoby: jako pojedynczy plik APK lub jako 2 osobne pliki APK. Jeśli rozpowszechniasz pojedynczy plik APK, będzie on obsługiwał pojazdy z systemem operacyjnym Android Automotive z hostem biblioteki aplikacji do samochodu i w razie potrzeby przełączy się na aplikację MediaBrowserService lub MediaLibraryService, nawet w przypadku starszych wersji Androida (Android 10–13). Jeśli zdecydujesz się rozpowszechniać 2 osobne pliki APK, możesz łatwiej aktualizować nowe dodatki do wersji biblioteki aplikacji do samochodu bez obawy o wpływ na wersję MediaBrowserService lub MediaLibraryService w aplikacji.
Rozpowszechnianie pojedynczego pliku APK
Podczas rozpowszechniania pojedynczego pliku APK dla biblioteki aplikacji do samochodu oraz MediaBrowserService
lub MediaLibraryService wersji aplikacji ważne jest, aby ustawić
"android:required="false".
<uses-feature android:name="android.software.car.templates_host.media" android:required="false"/>
Następnie postępuj zgodnie z wytycznymi biblioteki aplikacji do samochodu dotyczącymi AAOS i
wprowadź uruchamialną CarAppActivity (lub aktywność trampolinową). W pliku manifestu musisz ustawić aktywność na android:enabled="false". Następnie dodaj tag metadanych do deklaracji MediaBrowserService, wskazując komponent CarAppActivity jako zamiennik. Poniżej znajdziesz przykładowy plik manifestu:
<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>
Dystrybucja w Google Play
Plik APK z biblioteką aplikacji do samochodu oraz MediaBrowserService lub MediaLibraryService powinien mieć włączoną wyższą wersję kodu i minSdk kierowany na Androida 14 (34).
Rozpowszechnianie za pomocą 2 plików APK
Aby rozpowszechniać 2 osobne pliki APK, jeden z biblioteką aplikacji do samochodu, a drugi z MediaBrowserService lub MediaLibraryService, wykonaj te czynności, aby prawidłowo kierować reklamy na odpowiednie funkcje pojazdu.
Podczas tworzenia osobnego pliku APK dla wersji biblioteki aplikacji do samochodu musisz ustawić android.software.car.templates_host.media na android:required=true. Dzięki temu aplikacja będzie rozpowszechniana tylko w kompilacjach systemu operacyjnego Android Automotive z certyfikatem obsługi hosta biblioteki aplikacji do samochodu.
<uses-feature android:name="android.software.car.templates_host.media" android:required="true"/>
Oprócz użycia android.software.car.templates_host.media i ustawienia go na
android:required=true wykonaj te czynności, aby włączyć system operacyjny Android Automotive
w przypadku uruchamialnej aktywności biblioteki aplikacji do samochodu.
Dystrybucja w Google Play
Plik APK, który korzysta z biblioteki aplikacji do samochodu, powinien być rozpowszechniany na osobnej ścieżce Automotive OS.
Obsługa komend głosowych
Włącz obsługę komend głosowych w aplikacji, aby użytkownicy mogli wykonywać typowe czynności bez użycia rąk.
Szczegółowe instrukcje implementacji
znajdziesz w artykule Obsługa komend głosowych w przypadku multimediów. Jeśli w aplikacji do multimediów opartej na szablonach otrzymasz polecenie głosowe, nie musisz aktualizować MediaBrowserService ani MediaLibraryService o wyniki wyszukiwania. Zamiast tego rozważ dodanie działania w szablonie odtwarzania multimediów, które umożliwi użytkownikowi znajdowanie większej ilości treści na podstawie zapytania o odtwarzanie lub wyszukiwanie. Obsługa komend głosowych jest wymagana, aby spełnić VC-1 wytyczną dotyczącą jakości.
Tworzenie szablonu odtwarzania
The MediaPlaybackTemplate displays media playback
information in your Car App Library media app. This template allows setting a
header with a title and customizable actions while the media information and
playback controls are populated by the host based off of the state of your app's
MediaSession.
Rysunek 1.
MediaPlaybackTemplate z działaniem w nagłówku, które umożliwia otwarcie kolejki u góry.
Ten przykład kodu pokazuje, jak utworzyć przykładowy szablon odtwarzania, który ustawia działanie w nagłówku umożliwiające użytkownikowi przejście do ekranu z kolejką utworów.
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()
Gdy używasz MediaPlaybackTemplate, zarejestruj a
MediaSession token za pomocą MediaPlaybackManager w your
CarAppService. Jeśli tego nie zrobisz, podczas wysyłania MediaPlaybackTemplate do hosta wyświetli się błąd.
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 jest niezbędny do udostępniania informacji o odtwarzaniu multimediów i elementów sterujących w Androidzie Auto. Jest to też ważne, aby host mógł tworzyć powiadomienia dotyczące multimediów.
W przypadku aplikacji korzystających z biblioteki Media3, które używają PlatformToken zamiast standardowego MediaSessionCompat.Token, musisz zaimplementować niestandardową SessionCommand w MediaLibrarySession.Callback, która zwraca podstawowy token platformy sesji: session.platformToken. W CarAppService wyślij to niestandardowe polecenie do sesji. Gdy otrzymasz token platformy, przekonwertuj go za pomocą
MediaSessionCompat.Token.fromToken(platformToken) i przekaż ten token zgodności
do biblioteki aplikacji do samochodu w .registerMediaPlaybackToken().
Porządkowanie multimediów za pomocą szablonów
Aby uporządkować multimedia do przeglądania, np. utwory lub albumy, zalecamy używanie
SectionedItemTemplate,
który umożliwia używanie razem GridSection i
RowSection do tworzenia układów łączących listy obrazów
i elementów tekstowych.
Rysunek 2. SectionedItemTemplate zawierający RowSection i GridSection
Używanie SectionedItemTemplate w TabTemplate
Wygodnym sposobem na kategoryzowanie multimediów w aplikacji jest używanie
SectionedItemTemplate w
TabTemplate.
val template =
SectionedItemTemplate.Builder()...build();
val tabTemplate =
TabTemplate.Builder(tabCallback)
.setTabContents(TabContents.Builder(template).build)
.setHeaderAction(Action.APP_ICON)
…
.build();
Komponenty i funkcje biblioteki aplikacji do samochodu w wersji 1.9
W wersji 1.9 biblioteki aplikacji do samochodu wprowadziliśmy dostosowane komponenty do unikalnych funkcji przeglądania, takie jak Chips, Progress Bars, Condensed Items, Interactive and Expanded Header, Spotlight Sections i Banners.
Rysunek 3. SectionedItemTemplate zawierający Chips, Condensed Items, Interactive Header, Grid Items i Minimized Control Panel
Rysunek 4. 2 ekrany przeglądania multimediów z Expanded Header, Spotlight Sections i Progress Bars
Więcej informacji o projektowaniu interfejsu aplikacji do multimediów za pomocą tych szablonów znajdziesz w artykule Aplikacje do multimediów.
Przechodzenie do elementów sterujących odtwarzaniem
Podczas przeglądania multimediów ważne jest, aby użytkownik mógł szybko
przejść do MediaPlaybackTemplate przy minimalnym rozpraszaniu uwagi.Aby spełnić wymaganie dotyczące jakości
MFT-1, aplikacja musi mieć możliwość uzyskania dostępu
do MediaPlaybackTemplate ze wszystkich ekranów przeglądania multimediów.
Jeśli używasz SectionedItemTemplate, możesz to zrobić, dodając przycisk polecenia, który przenosi użytkownika do ekranu odtwarzania multimediów. Użyj standardowego działania biblioteki aplikacji do samochodu Action.MEDIA_PLAYBACK. Aplikacja do multimediów wyświetli to działanie jako zminimalizowany panel sterowania, który jest wymagany do spełnienia wymagania dotyczącego jakości MFT-1, jeśli używasz biblioteki aplikacji do samochodu w wersji 1.9 lub nowszej. W przypadku innych szablonów można to zrobić za pomocą działania w nagłówku.
Obsługa intencji systemowego odtwarzania multimediów
Gdy aplikacja jest uruchamiana z powierzchni systemowej odtwarzającej multimedia, np. z karty multimediów, użytkownik musi zostać przekierowany do MediaPlaybackTemplate. Wymagamy, aby aplikacje do multimediów obsługiwały to Intent Action, aby
zapewnić użytkownikom płynne działanie.
Dodaj działanie androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK do
filtra intencji komponentu biblioteki aplikacji do samochodu (albo CarAppActivity lub
aktywności trampolinowej Activity).
Upewnij się, że aktywność używa launchMode o wartości singleTask lub singleTop, aby wywoływać 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>
W klasie Session zastąp onNewIntent(), aby przeanalizować przychodzącą intencję.
Jeśli przychodzące działanie intencji pasuje do SHOW_MEDIA_PLAYBACK, przekieruj użytkownika do ekranu odtwarzania.
@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));
}
}
Jeśli używasz aktywności trampolinowej, sprawdź działanie intencji w onCreate(). Przed wywołaniem finish() przekaż to działanie do intencji tworzenia 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();
}
}