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 devez implémenter 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 méthode onLoadChildren
. 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, nu
ll)
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 de package
Lorsqu'un appel est effectué vers la méthode onGetRoot
de votre service, le package à l'origine de l'appel 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 vérifié, renvoyez null
pour refuser l'accès à votre contenu.
Pour que les applications système (comme Android Auto et AAOS) puissent accéder à votre contenu, votre service doit renvoyer une valeur BrowserRoot
non nulle lorsque ces applications 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 provient de la classe PackageValidator
dans l'application exemple Universal Android Music Player sur GitHub. Reportez-vous à cette classe pour obtenir un exemple plus détaillé d'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 permettre à l'Assistant Google de se connecter à votre MediaBrowserService
. L'Assistant Google utilise des noms de package distincts pour le téléphone (ce qui inclut Android Auto) et pour Android Automotive OS (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 objet MediaBrowserCompat.MediaItem
. Chacun de ces éléments multimédias est identifié par une chaîne d'identifiant 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, une partie du contenu racine peut être supprimée ou rendue moins visible par le système.
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 suivez pas ces suggestions, il se peut qu'une partie du contenu racine soit supprimée ou que le système la rende moins visible. Ces suggestions sont transmises :
Limite du nombre d'enfants racines : dans la plupart des cas, ce nombre est égal à quatre, ce qui signifie que 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 de l'onglet
Des libellés courts et explicites pour chaque élément d'onglet (les libellés courts réduisent le risque de troncature)