Android Auto e Android Automotive OS ti aiutano a portare i contenuti delle tue app multimediali su in auto. Un'app multimediale per le auto deve fornire un servizio di browser multimediale in modo che Android Auto, Android Automotive OS o un'altra app con un un browser, può rilevare e visualizzare i tuoi contenuti.
Questa guida presuppone che tu abbia già un'app multimediale che riproduce audio su una smartphone e che la tua app multimediale sia conforme all'app multimediale Android dell'architettura.
Questa guida descrive i componenti obbligatori di un MediaBrowserService
e
MediaSession
necessari alla tua app per funzionare su Android Auto o Android
Automotive OS. Una volta completata l'infrastruttura multimediale di base, puoi
aggiungi il supporto per Android Auto e aggiungi il supporto per
Android Automotive OS per i tuoi contenuti multimediali
dell'app.
Prima di iniziare
- Consulta la documentazione dell'API Android Media.
- Leggi l'articolo Creare app multimediali per una guida alla progettazione.
- Esamina i termini e i concetti chiave elencati in questa sezione.
Termini e concetti chiave
- Servizio browser multimediale
- Un servizio Android implementato dalla tua app multimediale che sia conforme alle
MediaBrowserServiceCompat
tramite Google Cloud CLI o tramite l'API Compute Engine. L'app utilizza questo servizio per esporre i propri contenuti. - Browser multimediale
- Un'API utilizzata dalle app multimediali per trovare servizi browser multimediali e visualizzazione i relativi contenuti. Android Auto e Android Automotive OS utilizzano un browser multimediale per trova il servizio di browser multimediale della tua app.
- Elemento multimediale
Il browser multimediale organizza i propri contenuti in una struttura ad albero di
MediaItem
di oggetti strutturati. Un elemento multimediale può avere uno o entrambi i seguenti flag:FLAG_PLAYABLE
: indica che l'elemento è una foglia nell'albero dei contenuti. L'elemento rappresenta un singolo stream audio, come un brano di un album, un capitolo di un audiolibro o una puntata di un podcast.FLAG_BROWSABLE
: indica che l'elemento è un nodo nell'albero dei contenuti e che ha figli. Ad esempio, l'elemento rappresenta un album e i relativi elementi secondari sono i brani dell'album.
Un elemento multimediale sfogliabile e riproducibile funge da playlist. Puoi selezionare l'elemento per riprodurre tutti i relativi elementi secondari oppure sfogliare i suoi bambini.
- Ottimizzato per veicoli
Un'attività di un'app per il sistema operativo Android Automotive che rispetta le Linee guida per la progettazione del sistema operativo Android Automotive. L'interfaccia per queste attività non è disegnata da Android Automotive OS, quindi devi assicurarti che l'app rispetti le linee guida relative alla progettazione. In genere, include target dei tocchi e dimensioni dei caratteri più grandi, supporto per le modalità giorno e notte e rapporti di contrasto più elevati.
Le interfacce utente ottimizzate per i veicoli possono essere visualizzate solo quando il Le Restrizioni relative all'esperienza utente (CUXR) non sono attive perché possono richiedere maggiore attenzione o interazione da parte dell'utente. CUXR non sono attivi quando l'auto è ferma o parcheggiata, ma sono sempre attive quando l'auto è in movimento.
Non è necessario progettare attività per Android Auto, perché Android Auto trae la propria interfaccia ottimizzata per il veicolo utilizzando le informazioni del browser multimediale.
Configurare i file manifest dell'app
Prima di poter creare il tuo servizio di browser multimediale, devi configurare il tuo file manifest dell'app.
Dichiara il tuo servizio di browser multimediale
Sia Android Auto che Android Automotive OS si connettono alla tua app tramite di navigazione multimediale per sfogliare gli elementi multimediali. Dichiara i tuoi contenuti multimediali browser web nel file manifest per consentire ad Android Auto e Android Automotive OS scoprire il servizio e connettersi alla tua app.
Il seguente snippet di codice mostra come dichiarare il tuo servizio di browser multimediale in del file manifest. Includi questo codice nel file manifest per il tuo Modulo del sistema operativo Android Automotive e nel file manifest dell'app Telefono.
<application>
...
<service android:name=".MyMediaBrowserService"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
...
</application>
Specifica le icone delle app
Devi specificare le icone delle app che possono essere utilizzate da Android Auto e Android Automotive OS per rappresentare la tua app nella UI di sistema. Sono necessari due tipi di icona:
- Icona in Avvio applicazioni
- Icona di attribuzione
Icona in Avvio applicazioni
L'icona in Avvio applicazioni rappresenta la tua app nell'interfaccia utente di sistema, ad esempio in Avvio app e nella barra delle icone. Puoi specificare di utilizzare l'icona da la tua app mobile per rappresentare la tua app multimediale per auto utilizzando il seguente manifest dichiarazione:
<application
...
android:icon="@mipmap/ic_launcher"
...
/>
Per utilizzare un'icona diversa da quella dell'app mobile, imposta la proprietà android:icon
nell'elemento <service>
del tuo servizio di browser multimediali nel file manifest:
<application>
...
<service
...
android:icon="@mipmap/auto_launcher"
...
/>
</application>
Icona di attribuzione
L'icona dell'attribuzione viene utilizzata nelle posizioni in cui i contenuti multimediali hanno la precedenza, come nelle schede multimediali. Valuta la possibilità di riutilizzare la piccola icona usata per le notifiche. Questa icona deve essere monocromatica. Puoi specificare un'icona utilizzata per rappresentare la tua app utilizzando la seguente dichiarazione del file manifest:
<application>
...
<meta-data
android:name="androidx.car.app.TintableAttributionIcon"
android:resource="@drawable/ic_status_icon" />
...
</application>
Crea il tuo servizio di browser multimediale
Puoi creare un servizio di browser multimediale estendendo MediaBrowserServiceCompat
. Sia Android Auto che Android Automotive OS possono quindi utilizzare il tuo servizio
per effettuare le seguenti operazioni:
- Esplora la gerarchia dei contenuti della tua app per presentare un menu all'utente.
- Recuperare il token per
MediaSessionCompat
dell'app per controllare la riproduzione audio.
Puoi anche usare il tuo servizio di browser multimediale per consentire ad altri client accedere a contenuti multimediali dalla tua app. Questi client multimediali potrebbero essere altre app telefono dell'utente o altri client remoti.
Flusso di lavoro del servizio browser multimediale
Questa sezione descrive in che modo Android Automotive OS e Android Interagisci automaticamente con il tuo servizio di browser multimediali durante un flusso di lavoro utente tipico.
- L'utente avvia la tua app sul sistema operativo Android Automotive o Android Auto.
- Android Automotive OS o Android Auto contatta il browser multimediale della tua app
utilizzando
onCreate()
. Nella tua implementazione delonCreate()
devi creare e registrare unMediaSessionCompat
e il relativo oggetto callback. - Android Automotive OS o Android Auto chiama il
onGetRoot()
del tuo servizio per ottenere l'elemento multimediale principale nella gerarchia dei contenuti. L'elemento multimediale principale non viene visualizzato; ma viene utilizzato per recuperare più contenuti dalla tua app. - Android Automotive OS o Android Auto chiama
onLoadChildren()
per ottenere i figli dell'elemento multimediale principale. Android Automotive OS e Android Auto mostra questi elementi multimediali come livello superiore dei contenuti. Consulta: Strutturare il menu principale in questa pagina per ulteriori informazioni informazioni su ciò che il sistema si aspetta a questo livello. - Se l'utente seleziona un elemento multimediale sfogliabile, l'elemento
onLoadChildren()
viene richiamato per recuperare gli elementi secondari della voce di menu selezionata. - Se l'utente seleziona un elemento multimediale riproducibile, Android Automotive OS o Android Consente di chiamare automaticamente il metodo di callback della sessione multimediale appropriato per eseguire l'azione.
- Se la funzionalità è supportata dalla tua app, l'utente può anche cercare i tuoi contenuti. In questo
caso Android Automotive OS o Android Auto, chiama il
onSearch()
.
Creare la gerarchia dei contenuti
Android Auto e Android Automotive OS chiamano il servizio di browser multimediale della tua app a
per scoprire quali contenuti sono disponibili. Devi implementare due metodi nel
di browser multimediale per supportare questa funzionalità: onGetRoot()
e
onLoadChildren()
Implementare onGetRoot
La classe onGetRoot()
del tuo servizio
restituisce informazioni sul nodo radice della gerarchia dei contenuti.
Android Auto e Android Automotive OS utilizzano questo nodo principale per richiedere il resto di
i tuoi contenuti utilizzando
onLoadChildren()
.
Il seguente snippet di codice mostra una semplice implementazione
Metodo onGetRoot()
:
Kotlin
override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle? ): BrowserRoot? = // Verify that the specified package is allowed to access your // content. You'll need to write your own logic to do this. if (!isValid(clientPackageName, clientUid)) { // If the request comes from an untrusted package, return null. // No further calls will be made to other media browsing methods. null } else MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
Java
@Override public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) { // Verify that the specified package is allowed to access your // content. You'll need to write your own logic to do this. if (!isValid(clientPackageName, clientUid)) { // If the request comes from an untrusted package, return null. // No further calls will be made to other media browsing methods. return null; } return new MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null); }
Per un esempio più dettagliato di questo metodo, consulta la sezione onGetRoot()
nell'app di esempio Universal Android Music Player su GitHub.
Aggiungi la convalida del pacchetto per onGetRoot()
Quando viene effettuata una chiamata al servizio onGetRoot()
del tuo servizio
, il pacchetto chiamante passa le informazioni identificative al tuo servizio. Il tuo
servizio può usare queste informazioni per stabilire se il pacchetto può accedere ai tuoi
contenuti. Ad esempio, puoi limitare l'accesso ai contenuti della tua app a un elenco di
i pacchetti approvati confrontando clientPackageName
con la tua lista consentita e
la verifica del certificato utilizzato per firmare l'APK del pacchetto. Se il pacco non può
essere verificato, restituisce null
per negare l'accesso ai tuoi contenuti.
Per offrire app di sistema come Android Auto e Android Automotive OS,
con accesso ai tuoi contenuti, il tuo servizio deve sempre restituire un valore diverso da null
BrowserRoot
quando queste app di sistema chiamano onGetRoot()
. La firma dell'app di sistema del sistema operativo Android Automotive può variare a seconda
sulla marca e sul modello dell'auto, pertanto è necessario autorizzare i collegamenti
app di sistema per un solido sistema operativo Android Automotive.
Il seguente snippet di codice mostra in che modo il tuo servizio può confermare che per le chiamate è un'app di sistema:
fun isKnownCaller(
callingPackage: String,
callingUid: Int
): Boolean {
...
val isCallerKnown = when {
// If the system is making the call, allow it.
callingUid == Process.SYSTEM_UID -> true
// If the app was signed by the same certificate as the platform
// itself, also allow it.
callerSignature == platformSignature -> true
// ... more cases
}
return isCallerKnown
}
Questo snippet di codice è un estratto della serie PackageValidator
nell'app di esempio Universal Android Music Player su GitHub. Visualizza il corso
per un esempio più dettagliato di come implementare la convalida del pacchetto per
onGetRoot()
del servizio
.
Oltre a consentire le app di sistema, devi consentire all'Assistente Google
connettiti al tuo MediaBrowserService
. Tieni presente che l'Assistente Google ha
nomi di pacchetti separati
per lo smartphone, che include Android Auto, e per Android Automotive OS.
Implementazione di onLoadChildren()
Dopo aver ricevuto l'oggetto del nodo principale, Android Auto e Android Automotive OS
per creare un menu di primo livello chiamando onLoadChildren()
sull'oggetto nodo radice per ottenere i relativi figli. Le app client creano sottomenu
chiamandolo allo stesso metodo usando oggetti dei nodi figlio.
Ogni nodo della gerarchia dei contenuti è rappresentato da un elemento MediaBrowserCompat.MediaItem
. Ciascuno di questi elementi multimediali è identificato da una stringa ID univoca. Cliente
le app considerano queste stringhe ID come token opachi. Quando un'app client vuole navigare
a un sottomenu o riprodurre un elemento multimediale, il token viene trasmesso. La tua app è responsabile
per associare il token all'elemento multimediale appropriato.
Il seguente snippet di codice mostra una semplice implementazione di onLoadChildren()
:
Kotlin
override fun onLoadChildren( parentMediaId: String, result: Result<List<MediaBrowserCompat.MediaItem>> ) { // Assume for example that the music catalog is already loaded/cached. val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf() // Check whether this is the root menu: if (MY_MEDIA_ROOT_ID == parentMediaId) { // Build the MediaItem objects for the top level // and put them in the mediaItems list. } else { // Examine the passed parentMediaId to see which submenu we're at // and put the children of that menu in the mediaItems list. } result.sendResult(mediaItems) }
Java
@Override public void onLoadChildren(final String parentMediaId, final Result<List<MediaBrowserCompat.MediaItem>> result) { // Assume for example that the music catalog is already loaded/cached. List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); // Check whether this is the root menu: if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) { // Build the MediaItem objects for the top level // and put them in the mediaItems list. } else { // Examine the passed parentMediaId to see which submenu we're at // and put the children of that menu in the mediaItems list. } result.sendResult(mediaItems); }
Per un esempio completo di questo metodo, consulta
onLoadChildren()
nell'app di esempio Universal Android Music Player su GitHub.
Strutturare il menu principale
Android Auto e Android Automotive OS hanno vincoli specifici relativi a
della struttura del menu principale. Queste informazioni vengono comunicate al MediaBrowserService
tramite i suggerimenti radice, che possono essere letti mediante l'argomento Bundle
passato in
onGetRoot()
Seguendo questi suggerimenti consenti al sistema di visualizzare in modo ottimale i contenuti della directory principale
come schede di navigazione. Se non segui questi suggerimenti, alcuni contenuti root potrebbero
essere eliminati o resi meno rilevabili dal sistema. Vengono inviati due suggerimenti:
- Un limite al numero di elementi secondari principali: nella maggior parte dei casi, il numero previsto è quattro. Ciò significa che non possono essere visualizzate più di quattro schede.
- Flag supportati per gli elementi secondari principali:
questo valore può essere
MediaItem#FLAG_BROWSABLE
Ciò significa che solo gli elementi sfogliabili, non quelli riproducibili, possono essere mostrati come schede.
Usa il seguente codice per leggere i hint pertinenti:
Kotlin
import androidx.media.utils.MediaConstants // Later, in your MediaBrowserServiceCompat. override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle ): BrowserRoot { val maximumRootChildLimit = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT, /* defaultValue= */ 4) val supportedRootChildFlags = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ MediaItem.FLAG_BROWSABLE) // Rest of method... }
Java
import androidx.media.utils.MediaConstants; // Later, in your MediaBrowserServiceCompat. @Override public BrowserRoot onGetRoot( String clientPackageName, int clientUid, Bundle rootHints) { int maximumRootChildLimit = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT, /* defaultValue= */ 4); int supportedRootChildFlags = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ MediaItem.FLAG_BROWSABLE); // Rest of method... }
Puoi scegliere di suddividere la logica per la struttura della gerarchia dei contenuti
in base ai valori di questi suggerimenti, in particolare se la gerarchia varia
Integrazioni di MediaBrowser
al di fuori di Android Auto e Android Automotive OS.
Ad esempio, se normalmente mostri un elemento riproducibile principale, potresti voler nidificarlo
sotto un elemento sfogliabile root a causa del valore dei flag supportati
hint.
Oltre ai suggerimenti di base, ci sono un paio di linee guida aggiuntive da seguire per assicurarti che il rendering delle schede sia ottimale:
- Fornisci icone monocromatiche, preferibilmente bianche, per ogni voce della scheda.
- Fornisci etichette brevi ma significative per ogni elemento della scheda. Uso delle etichette brevi riduce la possibilità che le stringhe vengano troncate.
Illustrazione multimediale visualizzata
L'artwork per gli elementi multimediali deve essere trasmessa come URI locale utilizzando
ContentResolver.SCHEME_CONTENT
o ContentResolver.SCHEME_ANDROID_RESOURCE
.
Questo URI locale deve risolversi in una bitmap o in un vettore drawable nella
le risorse dell'applicazione. Per MediaDescriptionCompat
oggetti che rappresentano elementi in
la gerarchia dei contenuti, passa l'URI tramite setIconUri()
.
Per MediaMetadataCompat
oggetti che rappresentano l'elemento attualmente in riproduzione, passa il token
URI tramite putString()
,
utilizzando una delle seguenti chiavi:
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI
MediaMetadataCompat.METADATA_KEY_ART_URI
MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI
I passaggi seguenti spiegano come scaricare immagini da un URI web ed esporre
attraverso un URI locale. Per un esempio più completo, consulta
implementazione
di openFile()
e i metodi circostanti in Universal Android Music
Esempio di app con player.
Crea un URI
content://
corrispondente all'URI web. Il browser multimediale il servizio e la sessione multimediale trasmettono questo URI di contenuti ad Android Auto e Sistema operativo Android Automotive.Kotlin
fun Uri.asAlbumArtContentURI(): Uri { return Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(this.getPath()) // Make sure you trust the URI .build() }
Java
public static Uri asAlbumArtContentURI(Uri webUri) { return new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(webUri.getPath()) // Make sure you trust the URI! .build(); }
Nell'implementazione di
ContentProvider.openFile()
, controlla se un file esiste per l'URI corrispondente. In caso contrario, scarica il file immagine e memorizzalo nella cache. La Il seguente snippet di codice utilizza Glide.Kotlin
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? { val context = this.context ?: return null val file = File(context.cacheDir, uri.path) if (!file.exists()) { val remoteUri = Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.path) .build() val cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) cacheFile.renameTo(file) file = cacheFile } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) }
Java
@Nullable @Override public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { Context context = this.getContext(); File file = new File(context.getCacheDir(), uri.getPath()); if (!file.exists()) { Uri remoteUri = new Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.getPath()) .build(); File cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS); cacheFile.renameTo(file); file = cacheFile; } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); }
Per ulteriori dettagli sui fornitori di contenuti, consulta la sezione Creazione di contenuti dell'utente.
Applica stili di contenuti
Dopo aver creato la gerarchia dei contenuti utilizzando elementi sfogliabili o riproducibili, possono applicare stili di contenuti che determinano l'aspetto di questi elementi nell'auto.
Puoi utilizzare i seguenti stili di contenuti:
- Voci dell'elenco
-
Questo stile di contenuti dà la priorità a titoli e metadati rispetto alle immagini.
- Elementi della griglia
-
Questo stile di contenuti dà la priorità alle immagini rispetto ai titoli e ai metadati.
Impostare gli stili dei contenuti predefiniti
Puoi configurare valori predefiniti globali per la modalità di visualizzazione degli elementi multimediali includendo
alcune costanti nel pacchetto extra di BrowserRoot
del servizio
onGetRoot()
. Android Auto e Android Automotive OS leggono questo bundle e cercano
queste costanti per determinare lo stile appropriato.
I seguenti extra possono essere utilizzati come chiavi nel bundle:
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
: indica un suggerimento di presentazione per tutti gli elementi sfogliabili all'interno dell'albero di navigazione.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
: indica un suggerimento di presentazione per tutti gli elementi riproducibili all'interno dell'albero di navigazione.
Le chiavi possono essere mappate ai seguenti valori di costanti interi per influenzare la presentazione di tali elementi:
DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
: gli elementi corrispondenti vengono presentati come voci dell'elenco.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
: gli elementi corrispondenti vengono presentati come elementi della griglia.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM
: gli articoli corrispondenti vengono presentati come "categoria" le voci dell'elenco. Si tratta di in modo analogo agli elementi ordinari dell'elenco, ad eccezione del fatto che i margini della voce perché hanno un aspetto migliore quando sono piccole. Le icone devono essere disegnabili vettoriali in tinta. Questo hint dovrebbe essere fornito solo per gli elementi sfogliabili.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM
: gli articoli corrispondenti vengono presentati come "categoria" gli elementi della griglia. Si tratta di come gli elementi ordinari della griglia, ad eccezione del fatto che i margini vengono applicati della voce perché hanno un aspetto migliore quando sono piccole. Le icone devono essere disegnabili vettoriali in tinta. Questo hint dovrebbe essere fornito solo per gli elementi sfogliabili.
Il seguente snippet di codice mostra come impostare lo stile dei contenuti predefinito per elementi sfogliabili nelle griglie e riproducibili negli elenchi:
Kotlin
import androidx.media.utils.MediaConstants @Nullable override fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); return new BrowserRoot(ROOT_ID, extras); }
Impostare gli stili dei contenuti per elemento
L'API Content Style ti consente di sostituire lo stile dei contenuti predefinito per elementi multimediali sfogliabili, nonché qualsiasi elemento multimediale stesso.
Per eseguire l'override dell'impostazione predefinita per gli elementi secondari di un elemento multimediale sfogliabile, crea un
gruppo extra in MediaDescription
dell'elemento multimediale e aggiungere lo stesso
i suggerimenti citati in precedenza. DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
si applica ai bambini giocabili di quell'elemento, mentre
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
si applica all'elemento
sfogliabili.
Per sostituire l'impostazione predefinita per un determinato elemento multimediale stesso, non per il relativo
secondari, crea un bundle extra in MediaDescription
dell'elemento multimediale
e aggiungi un suggerimento con la chiave
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM
.
Utilizza gli stessi valori descritti in precedenza per specificare la presentazione di quell'elemento.
Il seguente snippet di codice mostra come creare un elemento MediaItem
sfogliabile che
sostituisce lo stile di contenuti predefinito sia per se stesso sia per i relativi elementi secondari. Stili
come elemento dell'elenco di categoria, i relativi elementi secondari sfogliabili come elementi elenco e
elementi secondari riproducibili come elementi griglia:
Kotlin
import androidx.media.utils.MediaConstants private fun createBrowsableMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createBrowsableMediaItem( String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE); }
Raggruppa gli elementi con i suggerimenti del titolo
Per raggruppare gli elementi multimediali correlati, utilizza un suggerimento per elemento. Ogni elemento multimediale
in un gruppo deve dichiarare un bundle extra nel proprio MediaDescription
che
include una mappatura con la chiave
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE
e un valore di stringa identico. Localizza questa stringa, che viene utilizzata come
titolo del gruppo.
Il seguente snippet di codice mostra come creare un MediaItem
con un sottogruppo
intestazione di "Songs"
:
Kotlin
import androidx.media.utils.MediaConstants private fun createMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs") mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createMediaItem(String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs"); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/); }
L'app deve passare tutti gli elementi multimediali che vuoi raggruppare come blocco contiguo. Ad esempio, supponiamo che tu voglia visualizzare due gruppi di elementi multimediali, "Brani" e "Album", in quest'ordine e la tua app passa cinque elementi multimediali nel seguente ordine:
- Elemento multimediale A con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Elemento multimediale B con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
- Elemento multimediale C con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Elemento multimediale D con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Elemento multimediale E con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
Poiché gli elementi multimediali per i "Brani" gruppo e "Album" gruppo non viene mantenuto in blocchi contigui, Android Auto e Android Automotive OS lo interpreta come i seguenti quattro gruppi:
- Gruppo 1 chiamato "Brani" contenente l'elemento multimediale A
- Gruppo 2 chiamato "Album" contenente l'elemento multimediale B
- Gruppo 3 chiamato "Brani" contenente gli elementi multimediali C e D
- Gruppo 4 chiamato "Album" contenente l'elemento multimediale E
Per visualizzare questi elementi in due gruppi, l'app deve trasmettere gli elementi multimediali nel nel seguente ordine:
- Elemento multimediale A con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Elemento multimediale C con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Elemento multimediale D con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Elemento multimediale B con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
- Elemento multimediale E con
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
Visualizza indicatori di metadati aggiuntivi
Puoi includere indicatori di metadati aggiuntivi per fornire un riepilogo informazioni relative ai contenuti nella struttura ad albero del browser multimediale e durante la riproduzione. All'interno del sfoglia l'albero, Android Auto e Android Automotive OS leggono gli extra associati con un elemento e cercare alcune costanti per determinare quali indicatori display. Durante la riproduzione di contenuti multimediali, Android Auto e Android Automotive OS leggono il metadati per la sessione multimediale e cercare determinate costanti per determinare indicatori da visualizzare.
Le seguenti costanti possono essere utilizzate in entrambe le descrizioni extra di MediaItem
e
MediaMetadata
extra:
EXTRA_DOWNLOAD_STATUS
: indica lo stato di download di un articolo. Utilizza questa costante come chiave; le costanti lunghe riportate di seguito sono i valori possibili:STATUS_DOWNLOADED
: l'elemento sia stato scaricato completamente.STATUS_DOWNLOADING
: l'elemento viene scaricato.STATUS_NOT_DOWNLOADED
: l'elemento non viene scaricato.
METADATA_KEY_IS_EXPLICIT
: indica se l'elemento include contenuti espliciti. Per indicare che un elemento è esplicitamente, usare questa costante come chiave eMETADATA_VALUE_ATTRIBUTE_PRESENT
come valore.
Le seguenti costanti possono essere utilizzate solo in MediaItem
extra delle descrizioni:
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
: indica lo stato di completamento dei contenuti nel formato lungo, come puntate di podcast o audiolibri. Usa questa costante come chiave: il seguente numero intero sono i valori possibili:DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED
: l'elemento non è stato riprodotto.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
: l'elemento è stato riprodotto parzialmente e la posizione corrente è da qualche parte al centro.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED
: l'elemento è stato completato.
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
: indica l'avanzamento del completamento dei contenuti nel formato lungo come un doppio compreso tra 0,0 e 1,0 inclusi. Questo extra fornisce ulteriori informazioniPARTIALLY_PLAYING
stato in modo che Android Auto o Android Automotive OS mostra un indicatore di avanzamento più significativo, come un barra di avanzamento. Se utilizzi questo extra, consulta la sezione aggiornando la barra di avanzamento nella visualizzazione Sfoglia durante la riproduzione dei contenuti di questa guida per scoprire come mantenere aggiornato l'indicatore dopo che impressione iniziale.
Per visualizzare gli indicatori che appaiono mentre l'utente sta sfogliando i contenuti multimediali
ad albero, crea un bundle extra che includa una o più di queste costanti e
passare quel bundle al metodo MediaDescription.Builder.setExtras()
.
Il seguente snippet di codice mostra come visualizzare gli indicatori per un contenuto multimediale esplicito completamento dell'elemento al 70%:
Kotlin
import androidx.media.utils.MediaConstants val extras = Bundle() extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED) extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7) val description = MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build() return MediaBrowserCompat.MediaItem(description, /* flags */)
Java
import androidx.media.utils.MediaConstants; Bundle extras = new Bundle(); extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED); extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build(); return new MediaBrowserCompat.MediaItem(description, /* flags */);
Per visualizzare gli indicatori per un elemento multimediale in riproduzione, puoi:
dichiara i valori Long
per METADATA_KEY_IS_EXPLICIT
o EXTRA_DOWNLOAD_STATUS
in MediaMetadataCompat
di mediaSession
. Non puoi visualizzare il
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
o
Indicatori DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
nella visualizzazione di riproduzione.
Il seguente snippet di codice mostra come indicare che il brano corrente nella la visualizzazione di riproduzione è esplicita e scaricata:
Kotlin
import androidx.media.utils.MediaConstants mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build())
Java
import androidx.media.utils.MediaConstants; mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build());
Aggiorna la barra di avanzamento nella visualizzazione Sfoglia durante la riproduzione dei contenuti
Come detto in precedenza, puoi utilizzare
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
per mostrare una barra di avanzamento per i contenuti parzialmente riprodotti nel
visualizzazione Sfoglia. Tuttavia, se un utente continua a riprodurre i contenuti parzialmente riprodotti
da Android Auto o Android Automotive OS, l'indicatore diventa
non è precisa con il passare del tempo.
Per Android Auto e Android Automotive OS
per mantenere aggiornata la barra di avanzamento, puoi fornire ulteriori informazioni
MediaMetadataCompat
e PlaybackStateCompat
per collegare i contenuti in corso a
gli elementi multimediali nella visualizzazione Sfoglia. Devono essere soddisfatti i seguenti requisiti per
per avere una barra di avanzamento che si aggiorna automaticamente:
- Una volta creato,
MediaItem
deve inviareDESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
nei suoi extra con un valore compreso tra 0,0 e 1,0 inclusi. - L'
MediaMetadataCompat
deve inviareMETADATA_KEY_MEDIA_ID
con un valore stringa uguale a ID elemento multimediale passato alMediaItem
. PlaybackStateCompat
deve includere un extra con la chiavePLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID
che viene mappato su un valore di stringa uguale ID elemento multimediale passato alMediaItem
.
Il seguente snippet di codice mostra come indicare che l'elemento attualmente in riproduzione è collegato a un elemento nella visualizzazione Sfoglia:
Kotlin
import androidx.media.utils.MediaConstants // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. val mediaItemExtras = Bundle() mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25) val description = MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build() return MediaBrowserCompat.MediaItem(description, /* flags */) // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()) val playbackStateExtras = Bundle() playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id") mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build())
Java
import androidx.media.utils.MediaConstants; // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. Bundle mediaItemExtras = new Bundle(); mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build(); return MediaBrowserCompat.MediaItem(description, /* flags */); // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()); Bundle playbackStateExtras = new Bundle(); playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id"); mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build());
Mostra risultati di ricerca sfogliabili
La tua app può fornire risultati di ricerca contestuali che vengono mostrati agli utenti quando avviano una query di ricerca. Visualizzazione di Android Auto e Android Automotive OS questi risultati attraverso interfacce delle query di ricerca o attraverso inviti che si alternano per le query effettuate in precedenza durante la sessione. Per saperne di più, consulta Supporta le azioni vocali di questa guida.
Per visualizzare risultati di ricerca sfogliabili, includi il tasto costante
BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED
nel pacchetto extra del servizio onGetRoot()
del tuo servizio
, mappando il valore booleano true
.
Il seguente snippet di codice mostra come attivare l'assistenza in onGetRoot()
:
Kotlin
import androidx.media.utils.MediaConstants @Nullable fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true); return new BrowserRoot(ROOT_ID, extras); }
Per iniziare a fornire risultati di ricerca, sostituisci onSearch()
nel tuo servizio di browser multimediale. Android Auto e Android Automotive OS
inoltra i termini di ricerca dell'utente a questo metodo ogni volta che un utente richiama una ricerca
dell'interfaccia di query o "Risultati di ricerca".
Puoi organizzare la ricerca
risultati dal metodo onSearch()
del tuo servizio utilizzando elementi titolo
per renderli più facili da consultare. Ad esempio, se la tua app riproduce musica, potresti
Organizzare i risultati di ricerca per album, artista e brani.
Il seguente snippet di codice mostra una semplice implementazione dell'onSearch()
:
Kotlin
fun onSearch(query: String, extras: Bundle) { // Detach from results to unblock the caller (if a search is expensive). result.detach() object:AsyncTask() { internal var searchResponse:ArrayList internal var succeeded = false protected fun doInBackground(vararg params:Void):Void { searchResponse = ArrayList() if (doSearch(query, extras, searchResponse)) { succeeded = true } return null } protected fun onPostExecute(param:Void) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse) } else { // This invokes onError() on the search callback. result.sendResult(null) } return null } }.execute() } // Populates resultsToFill with search results. Returns true on success or false on error. private fun doSearch( query: String, extras: Bundle, resultsToFill: ArrayList ): Boolean { // Implement this method. }
Java
@Override public void onSearch(final String query, final Bundle extras, Result<List<MediaItem>> result) { // Detach from results to unblock the caller (if a search is expensive). result.detach(); new AsyncTask<Void, Void, Void>() { List<MediaItem> searchResponse; boolean succeeded = false; @Override protected Void doInBackground(Void... params) { searchResponse = new ArrayList<MediaItem>(); if (doSearch(query, extras, searchResponse)) { succeeded = true; } return null; } @Override protected void onPostExecute(Void param) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse); } else { // This invokes onError() on the search callback. result.sendResult(null); } } }.execute() } /** Populates resultsToFill with search results. Returns true on success or false on error. */ private boolean doSearch(String query, Bundle extras, ArrayList<MediaItem> resultsToFill) { // Implement this method. }
Azioni di navigazione personalizzate
Le azioni di navigazione personalizzate ti consentono di aggiungere etichette ed icone personalizzate al
MediaItem
oggetti nell'app multimediale dell'auto e gestire le interazioni degli utenti con
queste azioni. Questo ti consente di estendere la funzionalità dell'app Media in un
in diversi modi, ad esempio aggiungendo "Scarica", "Aggiungi alla coda", "Fammi ascoltare la radio"
"Preferiti" o "Rimuovi" azioni.
Se esistono più azioni personalizzate di quelle consentite dall'OEM, verrà presentato all'utente un menu extra.
Come funzionano?
Ogni azione di navigazione personalizzata è definita con:
- Un ID azione (un identificatore di stringa univoco)
- Un'etichetta dell'azione (il testo visualizzato dall'utente)
- Un URI dell'icona di azione (un elemento disegnabile vettoriale che può essere colorato)
Definisci un elenco di azioni di navigazione personalizzate a livello globale nell'ambito
BrowseRoot
. Quindi puoi collegare un sottoinsieme di queste azioni a singole
MediaItem.
Quando un utente interagisce con un'azione di navigazione personalizzata, l'app riceve un callback
a onCustomAction()
. Puoi quindi gestire l'azione e aggiornare l'elenco
azioni per MediaItem
, se necessario. È utile per le azioni stateful
come "Preferiti" e "Scarica". Per le azioni che non devono essere aggiornate, ad esempio "Riproduci
Radio", non devi aggiornare l'elenco delle azioni.
Puoi anche collegare le azioni di esplorazione personalizzate a una radice del nodo di navigazione. Queste azioni verranno visualizzati in una barra degli strumenti secondaria sotto la barra degli strumenti principale.
Come implementare le azioni di navigazione personalizzate
Per aggiungere azioni di esplorazione personalizzate al tuo progetto:
- Esegui l'override di due metodi
MediaBrowserServiceCompat
implementazione: - Analizza i limiti di azioni in fase di runtime:
- In
onGetRoot()
, ottieni il numero massimo di azioni consentite per ciascunoMediaItem
usando la chiaveBROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT
: nelrootHints
Bundle
. Un limite di 0 indica che la caratteristica è non supportate dal sistema.
- In
- Crea l'elenco globale di azioni di esplorazione personalizzate:
- Per ogni azione, crea un oggetto
Bundle
con le seguenti chiavi: *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
: l'ID azione *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
: l'etichetta dell'azione *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
: l'URI dell'icona di azione * Aggiungi tutti gli oggetti di azioneBundle
a un elenco.
- Per ogni azione, crea un oggetto
- Aggiungi l'elenco globale a
BrowseRoot
:- Nella sezione
Bundle
degli extra diBrowseRoot
, aggiungi l'elenco di azioni comeParcelable
Arraylist
utilizzando la chiaveBROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST
.
- Nella sezione
- Aggiungi azioni agli oggetti
MediaItem
:- Puoi aggiungere azioni a singoli oggetti
MediaItem
includendo l'elemento elenco di ID azione negli extra diMediaDescriptionCompat
che utilizzano la chiaveDESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST
Questo elenco deve essere un sottoinsieme dell'elenco globale di azioni definito inBrowseRoot
.
- Puoi aggiungere azioni a singoli oggetti
- Gestire le azioni e restituire l'avanzamento o i risultati:
- In
onCustomAction
, gestisci l'azione in base all'ID azione e a qualsiasi gli altri dati necessari. Puoi ottenere l'ID diMediaItem
che ha attivato l'azione dagli extra utilizzando la chiaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID
- Puoi aggiornare l'elenco di azioni per un
MediaItem
includendo l'elemento chiaveEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
nel pacchetto di progressi o risultati.
- In
Per iniziare, ecco alcune modifiche che puoi apportare nel tuo BrowserServiceCompat
con Azioni di esplorazione personalizzate.
Esegui l'override di BrowserServiceCompat
Devi eseguire l'override dei seguenti metodi in MediaBrowserServiceCompat
.
public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result)
public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result<Bundle> result)
Limite azioni di analisi
Dovresti verificare quante azioni di esplorazione personalizzate sono supportate.
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT, 0) }
Creare un'azione di navigazione personalizzata
Ogni azione deve essere compressa in un elemento Bundle
separato.
- ID azione
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, "<ACTION_ID>")
- Etichetta azione
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, "<ACTION_LABEL>")
- URI dell'icona di azione
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, "<ACTION_ICON_URI>")
Aggiungi azioni di navigazione personalizzate a Parceable
ArrayList
Aggiungi tutti gli oggetti dell'azione di navigazione personalizzata Bundle
in un ArrayList
.
private ArrayList<Bundle> createCustomActionsList( CustomBrowseAction browseActions) { ArrayList<Bundle> browseActionsBundle = new ArrayList<>(); for (CustomBrowseAction browseAction : browseActions) { Bundle action = new Bundle(); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, browseAction.mId); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, getString(browseAction.mLabelResId)); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, browseAction.mIcon); browseActionsBundle.add(action); } return browseActionsBundle; }
Aggiungi l'elenco Azioni di esplorazione personalizzate alla directory principale di navigazione
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { Bundle browserRootExtras = new Bundle(); browserRootExtras.putParcelableArrayList( BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST, createCustomActionsList())); mRoot = new BrowserRoot(ROOT_ID, browserRootExtras); return mRoot; }
Aggiungi azioni a MediaItem
MediaDescriptionCompat buildDescription (long id, String title, String subtitle, String description, Uri iconUri, Uri mediaUri, ArrayList<String> browseActionIds) { MediaDescriptionCompat.Builder bob = new MediaDescriptionCompat.Builder(); bob.setMediaId(id); bob.setTitle(title); bob.setSubtitle(subtitle); bob.setDescription(description); bob.setIconUri(iconUri); bob.setMediaUri(mediaUri); Bundle extras = new Bundle(); extras.putStringArrayList( DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST, browseActionIds); bob.setExtras(extras); return bob.build(); } MediaItem mediaItem = new MediaItem(buildDescription(...), flags);
Risultato della build onCustomAction
- Analizza mediaId da
Bundle extras
:@Override public void onCustomAction( @NonNull String action, Bundle extras, @NonNull Result<Bundle> result){ String mediaId = extras.getString(MediaConstans.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID); }
- Per ottenere risultati asincroni, scollega il risultato.
result.detach()
- Bundle di risultati della build
- Messaggio all'utente
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE, mContext.getString(stringRes))
- Aggiorna elemento(da utilizzare per aggiornare le azioni in un elemento)
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
- Apri visualizzazione riproduzione
//Shows user the PBV without changing the playback state mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
- Aggiornamento nodo esplorazione
//Change current browse node to mediaId mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
- Messaggio all'utente
- In caso di errore, chiama
result.sendError(resultBundle).
- Se l'avanzamento viene aggiornato, chiama il numero
result.sendProgressUpdate(resultBundle)
. - Termina chiamando il numero
result.sendResult(resultBundle)
.
Aggiornamento stato azione
Se utilizzi il metodo result.sendProgressUpdate(resultBundle)
con
EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
puoi aggiornare MediaItem
per riflettere il nuovo stato dell'azione. Questo
consente di fornire all'utente un feedback in tempo reale sui progressi e
risultato della loro azione.
Esempio: azione di download
Ecco un esempio di come utilizzare questa funzionalità per implementare un'azione di download con tre stati:
- Download: lo stato iniziale dell'azione. Quando l'utente seleziona
questa azione, puoi scambiarla con "Download" e chiama
sendProgressUpdate
per aggiornare la UI. - Download: questo stato indica che il download è in corso. Puoi utilizza questo stato per mostrare all'utente una barra di avanzamento o un altro indicatore.
- Scaricato: questo stato indica che il download è stato completato. Quando
finisci il download, puoi scambiare "Download" con "Scaricato" e chiama
sendResult
conEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
per indicare che l'elemento deve essere aggiornato. Inoltre, puoi utilizzare ilEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE
per mostrare all'utente un messaggio di operazione riuscita.
Questo approccio ti consente di fornire all'utente un feedback chiaro riguardo al download processo e il suo stato attuale. Puoi aggiungere ancora più dettagli con icone da mostrare Stati di download 25%, 50% e 75%.
Esempio: azione preferita
Un altro esempio è un'azione preferita con due stati:
- Preferito: questa azione viene visualizzata per gli elementi che non sono in
preferiti dell'utente. Quando l'utente seleziona questa azione, puoi scambiarla
con "Preferiti" e chiama
sendResult
conEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
per aggiornare l'interfaccia utente. - Preferito: questa azione viene visualizzata per gli elementi presenti nella
l'elenco dei preferiti. Quando l'utente seleziona questa azione, puoi scambiarla con
"Preferito" e chiama
sendResult
conEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
per aggiornare l'interfaccia utente.
Questo approccio offre agli utenti un modo chiaro e coerente per gestire preferiti.
Questi esempi mostrano la flessibilità delle azioni di navigazione personalizzate e i modi in cui usarle per implementare una varietà di funzionalità con feedback in tempo reale per per offrire un'esperienza utente migliorata nell'app multimediale dell'auto.
Per un esempio completo di implementazione di questa funzionalità, puoi fare riferimento alle
TestMediaApp
progetto.
Attiva il controllo di riproduzione
Android Auto e Android Automotive OS inviano i comandi di controllo della riproduzione tramite
MediaSessionCompat
del tuo servizio.
Devi registrare una sessione e implementare i metodi di callback associati.
Registrare una sessione multimediale
Nel file onCreate()
del tuo servizio di browser multimediali
crea un MediaSessionCompat
,
quindi registra la sessione multimediale chiamando setSessionToken()
.
Il seguente snippet di codice mostra come creare e registrare una sessione multimediale:
Kotlin
override fun onCreate() { super.onCreate() ... // Start a new MediaSession. val session = MediaSessionCompat(this, "session tag").apply { // Set a callback object that implements MediaSession.Callback // to handle play control requests. setCallback(MyMediaSessionCallback()) } sessionToken = session.sessionToken ... }
Java
public void onCreate() { super.onCreate(); ... // Start a new MediaSession. MediaSessionCompat session = new MediaSessionCompat(this, "session tag"); setSessionToken(session.getSessionToken()); // Set a callback object that implements MediaSession.Callback // to handle play control requests. session.setCallback(new MyMediaSessionCallback()); ... }
Quando crei l'oggetto sessione multimediale, imposti un oggetto callback che viene utilizzato
per gestire le richieste di controllo della riproduzione. Per creare questo oggetto di callback
fornendo un'implementazione di MediaSessionCompat.Callback
per la tua app. La prossima sezione illustra come implementare questo oggetto.
Implementa i comandi di riproduzione
Quando un utente richiede la riproduzione di un elemento multimediale dalla tua app, Android Automotive
Il sistema operativo e Android Auto utilizzano MediaSessionCompat.Callback
corso dal MediaSessionCompat
della tua app
ottenuto dal servizio di browser multimediale della tua app. Quando un utente
vuole controllare la riproduzione dei contenuti, ad esempio mettendo in pausa la riproduzione o passando
traccia successiva, Android Auto e Android Automotive OS richiamano
dei metodi dell'oggetto.
Per gestire la riproduzione dei contenuti, la tua app deve estendere l'astratto MediaSessionCompat.Callback
e implementare i metodi supportati dalla tua app.
Implementa tutti i seguenti metodi di callback pertinenti per il tipo di contenuti offerti dalla tua app:
onPrepare()
- Richiamato quando viene modificata la fonte multimediale. Android Automotive OS richiama anche questo metodo subito dopo l'avvio. L'app multimediale deve implementare questa funzionalità .
onPlay()
- Richiamato se l'utente sceglie di giocare senza scegliere un elemento specifico. Il tuo
all'app deve riprodurre i suoi contenuti predefiniti oppure, se la riproduzione è stata messa in pausa con
onPause()
, il tuo l'app riprende la riproduzione.Nota: la riproduzione di musica nell'app non dovrebbe iniziare automaticamente quando Android Automotive OS o Android Auto si connettono al browser multimediale completamente gestito di Google Cloud. Per ulteriori informazioni, consulta la sezione su l'impostazione dello stato di riproduzione iniziale.
onPlayFromMediaId()
- Richiamato quando l'utente sceglie di riprodurre un elemento specifico. Il metodo viene passato L'ID assegnato dal servizio di browser multimediale all'elemento multimediale nella gerarchia dei contenuti.
onPlayFromSearch()
- Richiamato quando l'utente sceglie di riprodurre il video da una query di ricerca. L'app deve fare una scelta appropriata in base alla stringa di ricerca trasmessa.
onPause()
- Richiamato quando l'utente sceglie di mettere in pausa la riproduzione.
onSkipToNext()
- Richiamato quando l'utente sceglie di passare all'elemento successivo.
onSkipToPrevious()
- Richiamato quando l'utente sceglie di passare all'elemento precedente.
onStop()
- Richiamato quando l'utente sceglie di interrompere la riproduzione.
Sostituisci questi metodi nell'app per fornire le funzionalità desiderate. Tu
non è necessario implementare un metodo se la sua funzionalità non è supportata dalla tua app. Per
Ad esempio, se la tua app riproduce un live streaming, come una trasmissione sportiva,
non è necessario implementare il metodo onSkipToNext()
. Puoi utilizzare il valore predefinito
implementazione di onSkipToNext()
.
La tua app non richiede alcuna logica speciale per riprodurre i contenuti tramite il speaker. Quando la tua app riceve una richiesta di riproduzione di contenuti, può riprodurre audio nello stesso modo in cui riproduce i contenuti tramite una gli altoparlanti o le cuffie dello smartphone. Android Auto e Android Automotive OS invia automaticamente i contenuti audio al sistema dell'auto per riprodurli su altoparlanti dell'auto.
Per ulteriori informazioni sulla riproduzione di contenuti audio, vedi Panoramica di MediaPlayer Panoramica dell'app audio, e la panoramica di ExoPlayer.
Impostare le azioni di riproduzione standard
Android Auto e Android Automotive OS mostrano i controlli di riproduzione in base al
azioni attivate nell'elemento PlaybackStateCompat
.
Per impostazione predefinita, l'app deve supportare le seguenti azioni:
La tua app può supportare anche le seguenti azioni, se pertinenti per i contenuti dell'app:
Inoltre, hai la possibilità di creare una coda di riproduzione che possa essere visualizzata
per l'utente, ma non è obbligatorio. A questo scopo, chiama setQueue()
e setQueueTitle()
abilita i metodi ACTION_SKIP_TO_QUEUE_ITEM
e definisci il callback onSkipToQueueItem()
.
Inoltre, aggiungi il supporto per l'icona Ora in riproduzione, che indica cosa
attualmente in riproduzione. A questo scopo, chiama setActiveQueueItemId()
e trasmette l'ID dell'elemento in coda al momento in riproduzione. Devi
aggiorna setActiveQueueItemId()
ogni volta che c'è un cambio di coda.
Pulsanti visualizzati di Android Auto e Android Automotive OS per ogni azione abilitata
nonché la coda di riproduzione. Quando i pulsanti sono
selezionato, il sistema richiama il callback corrispondente
MediaSessionCompat.Callback
Prenota spazio inutilizzato
Android Auto e Android Automotive OS riservano spazio nell'interfaccia utente per
ACTION_SKIP_TO_PREVIOUS
e ACTION_SKIP_TO_NEXT
azioni. Se la tua app
non supportano una di queste funzioni. Android Auto e Android Automotive OS utilizzano
nello spazio per visualizzare le azioni personalizzate che crei.
Se non vuoi riempire questi spazi con azioni personalizzate, puoi prenotare
in modo che Android Auto e Android Automotive OS lascino lo spazio vuoto.
ogni volta che l'app non supporta la funzione corrispondente. A questo scopo, chiama
setExtras()
con un bundle di extra che contiene costanti che corrispondono
funzioni riservate.
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT
corrisponde a ACTION_SKIP_TO_NEXT
e
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV
corrisponde a ACTION_SKIP_TO_PREVIOUS
. Utilizza queste costanti come chiavi
e utilizzano il valore booleano true
per i rispettivi valori.
Imposta PlaybackState iniziale
Android Auto e Android Automotive OS comunicano con il browser multimediale.
la tua sessione multimediale comunica lo stato della riproduzione dei contenuti utilizzando
PlaybackStateCompat
.
L'app non dovrebbe iniziare automaticamente la riproduzione di musica con il sistema operativo Android Automotive
o Android Auto per connetterti al tuo servizio di browser multimediale. Ci affidiamo ad Android
Auto e Android Automotive OS per riprendere o avviare la riproduzione in base al
o le azioni dell'utente.
A questo scopo, imposta il valore iniziale di PlaybackStateCompat
della tua sessione multimediale
STATE_STOPPED
,
STATE_PAUSED
STATE_NONE
,
o STATE_ERROR
.
Le sessioni multimediali in Android Auto e Android Automotive OS durano solo per il
durata del viaggio, quindi gli utenti avviano e interrompono spesso queste sessioni. A
promuovere un'esperienza fluida tra una guida e l'altra, tenere traccia dei precedenti
stato della sessione, in modo che quando l'app multimediale riceve
richiesta di ripristino, l'utente può riprendere automaticamente da dove ha interrotto
disattivata, ad esempio l'ultimo elemento multimediale riprodotto, PlaybackStateCompat
,
e la coda.
Aggiungere azioni di riproduzione personalizzate
Puoi aggiungere azioni di riproduzione personalizzate per visualizzare altre azioni che i tuoi
dell'app multimediale. Se lo spazio lo consente (e non è prenotato), Android aggiunge il parametro
azioni personalizzate ai controlli di trasporto. Altrimenti, le azioni personalizzate
nel menu extra. Le azioni personalizzate vengono visualizzate nell'ordine
vengono aggiunti a PlaybackStateCompat
.
Utilizza le azioni personalizzate per garantire un comportamento diverso da quello standard azioni. Non utilizzarle per sostituire o duplicare lo standard azioni.
Puoi aggiungere azioni personalizzate utilizzando la addCustomAction()
in PlaybackStateCompat.Builder
.
Il seguente snippet di codice mostra come aggiungere un'opzione personalizzata "Avvia un canale radio" azione:
Kotlin
stateBuilder.addCustomAction( PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon ).run { setExtras(customActionExtras) build() } )
Java
stateBuilder.addCustomAction( new PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon) .setExtras(customActionExtras) .build());
Per un esempio più dettagliato di questo metodo, consulta la sezione setCustomAction()
nell'app di esempio Universal Android Music Player su GitHub.
Dopo aver creato l'azione personalizzata, la sessione multimediale può rispondere all'azione
eseguendo l'override di onCustomAction()
.
Il seguente snippet di codice mostra come l'app potrebbe rispondere a un Azione "Avvia un canale radio":
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) { when(action) { CUSTOM_ACTION_START_RADIO_FROM_MEDIA -> { ... } } }
Java
@Override public void onCustomAction(@NonNull String action, Bundle extras) { if (CUSTOM_ACTION_START_RADIO_FROM_MEDIA.equals(action)) { ... } }
Per un esempio più dettagliato di questo metodo, consulta la sezione onCustomAction
nell'app di esempio Universal Android Music Player su GitHub.
Icone per azioni personalizzate
Ogni azione personalizzata che crei richiede una risorsa icona. Le app in auto possono vengono eseguiti su schermi di diverse dimensioni e densità, pertanto le icone che fornisci devono essere disegnabili vettoriali. R Vector drawable consente di ridimensionare gli asset senza perdere i dettagli. Un vettore drawable semplifica anche l'allineamento di bordi e angoli ai bordi dei pixel risoluzioni inferiori.
Se un'azione personalizzata è stateful, ad esempio, attiva o disattiva un'impostazione di riproduzione off: fornisci icone diverse per i vari stati, in modo che gli utenti vedere una modifica quando selezionano l'azione.
Fornisci stili alternativi per le icone per le azioni disattivate
Quando un'azione personalizzata non è disponibile per il contesto corrente, scambia l'icona dell'azione personalizzata con un'icona alternativa che indica che l'azione è disabilitata.
Indica il formato audio
Per indicare che i contenuti multimediali attualmente in riproduzione utilizzano un formato audio speciale:
puoi specificare le icone che vengono visualizzate nelle auto che supportano questa funzionalità. Tu
puoi impostare
KEY_CONTENT_FORMAT_TINTABLE_LARGE_ICON_URI
e ai
KEY_CONTENT_FORMAT_TINTABLE_SMALL_ICON_URI
nel bundle extra dell'elemento multimediale attualmente in riproduzione (passato a
MediaSession.setMetadata()
). Assicurati di impostare entrambi
di questi extra, per adattarli a layout diversi.
Puoi anche impostare KEY_IMMERSIVE_AUDIO
extra
per dire agli OEM di auto che si tratta di un audio immersivo, e devono fare molta attenzione
quando decidi se applicare effetti audio che potrebbero interferire con il
contenuti immersivi.
Aggiungi link dall'elemento in riproduzione
Puoi configurare l'elemento multimediale attualmente in riproduzione in modo che i relativi sottotitoli, descrizione o entrambi sono link ad altri elementi multimediali. Ciò consente all'utente di passare rapidamente elementi correlati; ad esempio passando ad altri brani dello stesso artista, altre puntate del podcast e così via. Se l'auto supporta questa funzionalità, gli utenti possono toccare il link per sfogliare quel contenuto.
Per aggiungere link, configura
Metadati KEY_SUBTITLE_LINK_MEDIA_ID
(al link dai sottotitoli) o
KEY_DESCRIPTION_LINK_MEDIA_ID
(per effettuare il collegamento da
la descrizione). Per maggiori dettagli, consulta la documentazione di riferimento relativa a questi
e i campi dei metadati.
Supporto delle azioni vocali
L'app multimediale deve supportare le azioni vocali per aiutare a fornire ai conducenti una e un'esperienza pratica che riduce al minimo le distrazioni. Ad esempio, se la tua app sta riproducendo un elemento multimediale, l'utente può dire "Riproduci [titolo del brano]" per indicare all'app di riprodurre un brano diverso senza guardare o toccare il display. Gli utenti possono avviare query facendo clic sui pulsanti appropriati sul volante o pronunciare la hotword "Hey Google".
Quando Android Auto o Android Automotive OS rileva e interpreta una voce
un'azione, l'azione vocale viene inviata all'app tramite
onPlayFromSearch()
Quando riceve questa chiamata, l'app trova contenuti corrispondenti ai query
stringa e avvia la riproduzione.
Gli utenti possono specificare diverse categorie di termini nella query: genere, artista,
l'album, il nome del brano, la stazione radio o la playlist. Durante la creazione
per la ricerca, prendi in considerazione tutte le categorie significative per la tua app.
Se Android Auto o Android Automotive OS rilevano che una determinata query rientra
alcune categorie, aggiunge extra nel parametro extras
. La
possono essere inviati i seguenti extra:
Considera una stringa query
vuota, che può essere inviata tramite
Android Auto o Android Automotive OS se l'utente non specifica termini di ricerca.
Ad esempio, se l'utente dice "Fammi sentire un po' di musica". In questo caso, la tua app potrebbe
scegli di avviare una traccia riprodotta di recente o appena suggerita.
Se non è possibile elaborare rapidamente una ricerca, non bloccarla in onPlayFromSearch()
.
Puoi invece impostare lo stato di riproduzione su STATE_CONNECTING
.
ed eseguire la ricerca su un thread asincrono.
Quando inizia la riproduzione, considera la possibilità di compilare la coda della sessione multimediale con contenuti correlati. Ad esempio, se l'utente richiede la riproduzione di un album, i tuoi l'app potrebbe riempire la coda con l'elenco di tracce dell'album. Valuta anche l'implementazione supporto dei risultati di ricerca sfogliabili in modo che l'utente possa scegliere una traccia diversa che corrisponda alla query.
Oltre che per "riproduci" query, Android Auto e Android Automotive OS
riconoscere query vocali per controllare la riproduzione, ad esempio "metti in pausa la musica" e "Avanti
brano" e abbinare questi comandi ai
callback appropriati della sessione multimediale,
come onPause()
e onSkipToNext()
.
Per un esempio dettagliato su come implementare le azioni di riproduzione vocali in la tua app, vedi Assistente Google e app multimediali.
Implementa misure di protezione contro le distrazioni
Perché lo smartphone di un utente è connesso agli altoparlanti dell'auto mentre utilizza Android Auto, devi adottare precauzioni aggiuntive per evitare di distrarre il conducente.
Disattiva gli allarmi nell'auto
Le app multimediali di Android Auto non devono iniziare a riprodurre l'audio dagli altoparlanti dell'auto a meno che l'utente non avvii la riproduzione, ad esempio premendo un pulsante di riproduzione. Anche una sveglia programmata dall'utente dalla tua app multimediale non deve avviarsi riproducendo musica dagli altoparlanti dell'auto.
Per soddisfare questo requisito, la tua app
è possibile utilizzare CarConnection
come segnale prima di riprodurre qualsiasi audio. L'app può controllare se lo smartphone è
viene proiettata sullo schermo di un'auto osservando il LiveData
per il collegamento dell'auto
tipo
e controllare se è uguale a
CONNECTION_TYPE_PROJECTION
.
Se lo smartphone dell'utente proietta, le app multimediali che supportano gli allarmi devono farlo delle seguenti opzioni:
- Disattiva la sveglia.
- Attiva la sveglia di oltre
STREAM_ALARM
e fornire un'UI sullo schermo dello smartphone per disattivare la sveglia.
Gestire gli annunci multimediali
Per impostazione predefinita, Android Auto mostra una notifica quando cambiano i metadati multimediali
durante una sessione di riproduzione audio. Quando un'app multimediale passa dalla riproduzione di musica
pubblicare una pubblicità, è distratto
notifica all'utente. Impedire ad Android Auto di visualizzare una notifica
In questo caso, devi impostare la chiave dei metadati
METADATA_KEY_IS_ADVERTISEMENT
a
METADATA_VALUE_ATTRIBUTE_PRESENT
,
come mostrato nello snippet di codice riportato di seguito:
Kotlin
import androidx.media.utils.MediaConstants override fun onPlayFromMediaId(mediaId: String, extras: Bundle?) { MediaMetadataCompat.Builder().apply { if (isAd(mediaId)) { putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) } // ...add any other properties you normally would. mediaSession.setMetadata(build()) } }
Java
import androidx.media.utils.MediaConstants; @Override public void onPlayFromMediaId(String mediaId, Bundle extras) { MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); if (isAd(mediaId)) { builder.putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); } // ...add any other properties you normally would. mediaSession.setMetadata(builder.build()); }
Gestire gli errori generali
Quando si verifica un errore nell'app, imposta lo stato di riproduzione su STATE_ERROR
e visualizzerai un messaggio di errore utilizzando setErrorMessage()
. Vedi PlaybackStateCompat
per visualizzare un elenco di codici di errore che puoi utilizzare durante l'impostazione del messaggio di errore.
I messaggi di errore devono essere rivolti all'utente e localizzati in base allo stato
impostazioni internazionali. Android Auto e Android Automotive OS possono quindi visualizzare l'errore
all'utente.
Ad esempio, se i contenuti non sono disponibili nella regione corrente dell'utente, puoi
utilizza la ERROR_CODE_NOT_AVAILABLE_IN_REGION
codice di errore durante l'impostazione del messaggio di errore.
Kotlin
mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build())
Java
mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build());
Per ulteriori informazioni sugli stati di errore, consulta Utilizzo di una sessione multimediale: stati ed errori.
Se un utente di Android Auto deve aprire l'app per smartphone per risolvere un errore: fornisci queste informazioni all'utente nel messaggio. Ad esempio, l'errore il messaggio potrebbe indicare "Accedi a [nome della tua app]" anziché "Accedi".