Android Auto et Android Automotive OS (AAOS) appellent le service de navigateur multimédia de votre application pour découvrir le contenu disponible. Pour cela, vous implémentez ces deux méthodes dans votre service de navigateur multimédia.
Implémenter onGetRoot
La méthode onGetRoot de votre service renvoie des informations sur le nœud racine
de votre hiérarchie de contenu. Android Auto et AAOS utilisent ce nœud
racine pour demander le reste du contenu à l'aide de la onLoadChildren
méthode. Cet extrait de code montre une implémentation de la méthode 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);
}
Pour obtenir un exemple détaillé de cette méthode, consultez onGetRoot dans l'application exemple Universal
Android Music Player sur GitHub.
Ajouter la validation du package
Lorsqu'un appel est effectué vers la méthode onGetRoot de votre service, le package appelant
transmet des informations d'identification à votre service. Votre service peut utiliser ces informations pour déterminer si ce package peut accéder à votre contenu.
Par exemple, vous pouvez limiter l'accès au contenu de votre application à une liste de packages approuvés :
- Comparez le
clientPackageNameà votre liste d'autorisation. - Vérifiez le certificat utilisé pour signer l'APK du package.
Si le package ne peut pas être validé, renvoyez null pour refuser l'accès à votre contenu.
Pour permettre aux applications système, telles qu'Android Auto et AAOS, d'accéder à votre contenu, votre service doit renvoyer un BrowserRoot non nul lorsque ces applications système appellent la méthode onGetRoot.
La signature de l'application système AAOS varie en fonction de la marque et du modèle d'une voiture. Veillez à autoriser les connexions de toutes les applications système pour prendre en charge AAOS.
Cet extrait de code montre comment votre service peut valider que le package appelant est une application système :
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
}
Cet extrait de code est un extrait de la PackageValidator classe dans l'
application exemple Universal Android Music Player sur GitHub. Consultez cette classe pour obtenir un exemple plus détaillé de l'implémentation de la validation de package pour la méthode onGetRoot de votre service.
En plus d'autoriser les applications système, vous devez autoriser l'Assistant Google à se connecter à votre MediaBrowserService. L'Assistant Google utilise des noms de package différents
pour ses applications mobiles et AAOS.
Implémenter onLoadChildren
Après avoir reçu votre objet de nœud racine, Android Auto et AAOS
créent un menu de niveau supérieur en appelant onLoadChildren sur cet objet
pour obtenir ses descendants. Les applications clientes créent des sous-menus en appelant cette même méthode à l'aide d'objets de nœuds descendants.
Chaque nœud de votre hiérarchie de contenu est représenté par un
MediaBrowserCompat.MediaItem objet. Chacun de ces éléments multimédias est identifié par une chaîne d'ID unique. Les applications clientes traitent ces chaînes d'identifiant comme des jetons opaques.
Lorsqu'une application cliente souhaite accéder à un sous-menu ou lire un élément multimédia, elle transmet le jeton. Votre application est chargée d'associer le jeton à l'élément multimédia approprié.
Cet extrait de code montre une implémentation de 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 if 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 descendants 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 if 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 descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems);
}
Pour voir un exemple de cette méthode, consultez onLoadChildren dans l'
application exemple Universal Android Music Player sur GitHub.
Structurer le menu racine
Android Auto et Android Automotive OS présentent des contraintes spécifiques concernant la structure du menu racine. Elles sont transmises à MediaBrowserService via des suggestions de racine qui peuvent être lues au moyen de l'argument Bundle transmis à onGetRoot(). En suivant ces suggestions, le système affiche le contenu racine sous forme d'onglets de navigation. Si vous ne suivez pas ces suggestions, le système risque de supprimer certains contenus racines ou de les rendre moins visibles.

Figure 1. Contenu racine affiché sous la forme d'onglets de navigation
En appliquant ces suggestions, le système affiche le contenu racine sous forme d'onglets de navigation. Si vous ne les appliquez pas, le système risque de supprimer certains contenus racines ou de les rendre moins visibles. Ces suggestions sont transmises :
Limite du nombre d'enfants racines : dans la plupart des cas, ce nombre est de quatre, ce qui signifie que seuls quatre onglets (ou moins) peuvent être affichés.
Indicateurs acceptés sur les enfants racines : cette valeur est généralement
MediaItem#FLAG_BROWSABLE, ce qui signifie que seuls les éléments consultables (et non les éléments lisibles) peuvent être affichés sous forme d'onglets.Limite du nombre d'actions de navigation personnalisées : vérifiez le nombre d'actions de navigation personnalisées acceptées.
Kotlin
import androidx.media.utils.MediaConstants
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...
}
Vous pouvez brancher la logique de votre hiérarchie de contenu en fonction des valeurs de ces suggestions, en particulier si votre hiérarchie varie entre les différentes intégrations de MediaBrowser en dehors d'Android Auto et d'AAOS.
Par exemple, si vous affichez normalement un élément racine pouvant être lu, vous pouvez, à la place, l'imbriquer dans un élément racine consultable, en raison de la valeur de la suggestion des indicateurs acceptés.
En plus des suggestions de racine, suivez ces consignes pour afficher les onglets de manière optimale :
Icônes monochromes (de préférence blanches) pour chaque élément d'onglet
Libellés courts et explicites pour chaque élément d'onglet (les libellés courts réduisent le risque de troncature)