Tworzenie aplikacji multimedialnej na podstawie szablonu

Aplikacje multimedialne na podstawie szablonu są w wersji beta
Obecnie każdy może publikować aplikacje multimedialne oparte na szablonach na ścieżkach testów wewnętrznych i zamkniętych w Sklepie Google Play. Publikowanie na ścieżkach otwartych i ścieżkach produkcyjnych będzie możliwe w późniejszym terminie.

Aplikacje multimedialne 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 zakładamy, że masz już aplikację do multimediów, która odtwarza dźwięk na telefonie i jest zgodna z architekturą aplikacji do multimediów na Androida. Biblioteka aplikacji do samochodu umożliwia zastąpienie interfejsu w aplikacji szablonami zamiast tych, które zostały utworzone przy użyciu struktury danych tworzenia aplikacji do multimediów na samochody. Nadal musisz udostępniać MediaSession do sterowania odtwarzaniem oraz MediaBrowserService lub MediaLibraryService, które są używane do rekomendacji i innych inteligentnych funkcji.MediaBrowser

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 samochodowej w filtrze intencji 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 na samochody

Aplikacje do multimediów korzystające z interfejsu MediaPlaybackTemplate są obsługiwane tylko w przypadku interfejsu CAL API w wersji 8 i nowszych. Upewnij się, że minimalna wersja interfejsu Car App API level jest ustawiona na 8.

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

Dodaj ikonę atrybucji

W przypadku aplikacji multimedialnych utworzonych przy użyciu biblioteki Car App Library dodaj ikonę atrybucji.

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 automotive_app_desc.xml w plikach XML zasobów. Powinna 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ę multimedialną z obsługą biblioteki aplikacji na samochody możesz rozpowszechniać w systemie operacyjnym Android Automotive na 2 sposoby: jako jeden plik APK lub jako 2 osobne pliki APK. Jeśli rozpowszechniasz jeden plik APK, będzie on obsługiwał pojazdy z systemem operacyjnym Android Automotive z hostem biblioteki aplikacji samochodowych i w razie potrzeby będzie przełączać 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 na samochody, nie martwiąc się o wpływ na wersję MediaBrowserService lub MediaLibraryService aplikacji.

Dystrybucja pojedynczego pakietu APK

Podczas rozpowszechniania pojedynczego pliku APK dla biblioteki aplikacji na samochody i wersji MediaBrowserService lub MediaLibraryService aplikacji konieczne jest ustawienie wartości „” na android:required="false".

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

Następnie postępuj zgodnie z wytycznymi dotyczącymi biblioteki aplikacji samochodowych na AAOS i wprowadź aktywność CarAppActivity, którą można uruchomić (lub aktywność trampolinową). W pliku manifestu musisz ustawić aktywność na android:enabled="false". Następnie dodaj do deklaracji MediaBrowserService tag metadanych wskazujący komponent CarAppActivity jako zamiennik. Zobacz przykładowy plik manifestu poniżej:

<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 na samochody i MediaBrowserService lub MediaLibraryService powinien mieć włączony wyższy kod wersji i właściwość minSdk kierowaną na Androida 14 (34).

Dystrybucja za pomocą 2 plików APK

Aby rozpowszechniać 2 osobne pliki APK, z których jeden korzysta z biblioteki aplikacji na samochody, a drugi z MediaBrowserService lub MediaLibraryService, wykonaj te czynności, aby mieć pewność, że prawidłowo kierujesz reklamy na odpowiednie funkcje pojazdu.

Podczas tworzenia osobnego pliku APK dla wersji aplikacji korzystającej z biblioteki aplikacji samochodowych musisz ustawić wartość android.software.car.templates_host.media na android:required=true. Dzięki temu aplikacja będzie rozpowszechniana tylko w przypadku kompilacji systemu operacyjnego Android Automotive z certyfikatem potwierdzającym obsługę hosta biblioteki aplikacji samochodowych.

<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 powyżej wykonaj te czynności, aby włączyć system operacyjny Android Automotive w przypadku aktywności biblioteki aplikacji samochodowych, którą można uruchomić.

Play Distribution

Plik APK, który korzysta z biblioteki aplikacji samochodowych, powinien być rozpowszechniany na dedykowanej ścieżce Automotive OS.

Obsługa komend głosowych

Włącz obsługę głosową w aplikacji, aby użytkownicy mogli wykonywać typowe działania bez użycia rąk. Więcej szczegółowych instrukcji wdrażania znajdziesz w artykule Obsługa działań głosowych w przypadku multimediów. Jeśli korzystasz z aplikacji do multimediów opartej na szablonie i otrzymasz polecenie głosowe, nie musisz aktualizować elementów MediaBrowserService ani MediaLibraryService o wyniki wyszukiwania. Zamiast tego możesz dodać działanie w szablonie odtwarzania multimediów, aby umożliwić użytkownikowi znajdowanie większej liczby treści na podstawie odtwarzania lub zapytania. Obsługa poleceń głosowych jest wymagana, aby spełnić wytyczne dotyczące jakości VC-1.

Tworzenie szablonu odtwarzania

Szablon MediaPlaybackTemplate wyświetla informacje o odtwarzaniu multimediów w aplikacji do multimediów w Bibliotece aplikacji na samochód. Ten szablon umożliwia ustawienie nagłówka z tytułem i dostosowywanymi działaniami, a informacje o multimediach i elementy sterujące odtwarzaniem są wypełniane przez hosta na podstawie stanu MediaSession aplikacji.

Odtwarzacz muzyki wyświetla utwór Sounds of Spring Summer Fielding z kwadratowym portretem kobiety grającej na gitarze.

Ilustracja 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 nagłówka 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 token MediaSession za pomocą MediaPlaybackManagerCarAppService. W przeciwnym razie podczas wysyłania znaku MediaPlaybackTemplate do hosta będzie wyświetlany 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 i elementów sterujących odtwarzaniem multimediów w Androidzie Auto. Jest to również 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ć niestandardowy SessionCommandMediaLibrarySession.Callback, który zwraca token platformy bazowej sesji: session.platformToken. W CarAppService wyślij do sesji to polecenie niestandardowe. Po otrzymaniu tokena platformy przekonwertuj go za pomocą funkcji MediaSessionCompat.Token.fromToken(platformToken) i przekaż ten token zgodności do biblioteki aplikacji na samochody w funkcji .registerMediaPlaybackToken().

Porządkowanie multimediów za pomocą szablonów

Do porządkowania multimediów, takich jak utwory lub albumy, zalecamy używanie komponentu SectionedItemTemplate, który umożliwia łączenie komponentów GridSection i RowSection w celu tworzenia układów zawierających listy obrazów i elementów tekstowych.

Interfejs aplikacji do odtwarzania muzyki wyświetla ostatnio odtwarzane utwory i albumy, w tym 2 pionowe rzędy i 3 poziome okładki albumów.

Ilustracja 2. Element SectionedItemTemplate zawierający element RowSection, a następnie element GridSection

Używanie szablonu SectionedItemTemplate w szablonie TabTemplate

Wygodnym sposobem kategoryzowania multimediów w aplikacji jest użycie elementu SectionedItemTemplate w ramach elementu 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 samochodowych w wersji 1.9

Car App Library API w wersji 1.9 wprowadza dostosowane komponenty, które zapewniają unikalne możliwości przeglądania, takie jak elementy, paski postępu, skrócone elementy, interaktywny i rozwijany nagłówek, sekcje wyróżnionebanery.

Interfejs aplikacji do odtwarzania muzyki wyświetla ostatnio odtwarzane utwory i albumy, w tym 2 pionowe rzędy i 3 poziome okładki albumów.

Ilustracja 3. Element SectionedItemTemplate zawierający Chips, Condensed Items, Interactive Header, Grid ItemsMinimized Control Panel

Interfejs aplikacji do odtwarzania muzyki wyświetla ostatnio odtwarzane utwory i albumy, w tym 2 pionowe rzędy i 3 poziome okładki albumów.

Ilustracja 4. Dwa ekrany przeglądania multimediów z ikonami Expanded Header, Spotlight SectionsProgress Bars.

Więcej informacji o projektowaniu interfejsu użytkownika aplikacji multimedialnej za pomocą tych szablonów znajdziesz w sekcji Aplikacje multimedialne.

Podczas przeglądania multimediów użytkownik musi mieć możliwość szybkiego przejścia do MediaPlaybackTemplate przy minimalnym rozproszeniu uwagi.Aby spełnić wymagania dotyczące jakości MFT-1, aplikacja musi umożliwiać dostęp do MediaPlaybackTemplate ze wszystkich ekranów przeglądania multimediów.

Jeśli używasz SectionedItemTemplate, możesz to zrobić, dodając przycisk działania, który przeniesie Cię na ekran odtwarzania multimediów. Użyj standardowego działania Action.MEDIA_PLAYBACK biblioteki aplikacji samochodowych. Aplikacja do multimediów wyświetli to działanie jako zminimalizowany panel sterowania, który jest wymagany do spełnienia wymagania jakości MFT-1, jeśli używasz interfejsu Car App Library API w wersji 1.9 lub nowszej. W przypadku innych szablonów możesz to zrobić, używając działania w nagłówku.

Obsługa intencji systemowych dotyczących odtwarzania multimediów

Wymagamy, aby po uruchomieniu aplikacji z poziomu systemu odtwarzającego multimedia, np. karty multimedialnej, użytkownik był kierowany do MediaPlaybackTemplate. Wymagamy, aby aplikacje multimedialne obsługiwały ten Intent Action, aby zapewnić użytkownikom bezproblemowe korzystanie z nich.

Dodaj działanie androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK do filtra intencji komponentu biblioteki aplikacji na samochody (CarAppActivity lub trampoliny Activity).

Upewnij się, że Twoja aktywność korzysta z launchMode singleTask lub singleTop, aby wywołać 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 metodę onNewIntent(), aby przeanalizować przychodzącą intencję. Jeśli działanie przychodzącej intencji pasuje do SHOW_MEDIA_PLAYBACK, przenieś użytkownika na ekran 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 związanej z trampoliną, sprawdź działanie intencji w onCreate(). Przekaż tę czynność do intencji utworzenia CarAppActivity przed wywołaniem finish().

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();
    }
}