Créer et tester une application à utiliser à l'arrêt pour Android Automotive OS : prise en charge de l'audio pendant la conduite

1. Avant de commencer

Ce que cet atelier n'est pas

  • Un guide expliquant comment créer des applications multimédias (audio, par exemple musique, radio, podcasts) pour Android Auto et Android Automotive OS. Consultez la page Créer des applications multimédias pour voitures pour découvrir comment créer de telles applis.

Ce dont vous avez besoin

Objectifs de l'atelier

Dans cet atelier de programmation, vous allez apprendre à ajouter la prise en charge de l'audio pendant la conduite dans Road Reels, une application existante compatible avec les appareils mobiles et Android Automotive OS.

Version de départ de la mise en pause de la lecture lorsque les restrictions sur l'expérience utilisateur sont actives.

Version terminée de l'application qui continue la lecture lorsque les restrictions sur l'expérience utilisateur sont actives.

Points abordés

  • Activer la lecture audio en arrière-plan dans une application vidéo sur Android Automotive OS

2. Configuration

Obtenir le code

  1. Le code pour cet atelier de programmation se trouve dans le répertoire build-a-parked-app au sein du dépôt GitHub car-codelabs. Pour le cloner, exécutez la commande suivante :
git clone https://github.com/android/car-codelabs.git
  1. Vous pouvez aussi télécharger le dépôt sous la forme d'un fichier ZIP :

Télécharger le fichier ZIP

Ouvrir le projet

  • Après avoir démarré Android Studio, importez le projet en sélectionnant uniquement le répertoire build-a-parked-app/end. Le répertoire build-a-parked-app/audio-while-driving contient le code de solution, que vous pouvez consulter à tout moment en cas de difficulté ou pour avoir un aperçu du projet dans son ensemble.

Vous familiariser avec le code

  • Après avoir ouvert le projet dans Android Studio, prenez le temps d'examiner le code de démarrage.

3. En savoir plus sur les applications à utiliser à l'arrêt pour Android Automotive OS

Les applications à utiliser à l'arrêt constituent un sous-ensemble des catégories d'applications compatibles avec Android Automotive OS. Au moment de la rédaction de cet atelier, il s'agit d'applications de streaming vidéo, de navigateurs Web et de jeux. Ces applications sont idéales pour les voitures, compte tenu du matériel présent dans les véhicules avec Google intégré et de la prévalence croissante des véhicules électriques, dont le temps de recharge représente une excellente opportunité pour les conducteurs et les passagers d'utiliser ce type d'applications.

À bien des égards, les voitures sont semblables à d'autres appareils à grand écran, comme les tablettes et les appareils pliables. Elles sont équipées d'écrans tactiles de taille, résolution et format similaires, en mode Portrait ou Paysage (mais, contrairement aux tablettes, leur orientation est fixe). Ce sont également des appareils connectés qui peuvent se connecter et se déconnecter du réseau. En tenant compte de tous ces éléments, il n'est pas surprenant que les applications déjà optimisées pour les grands écrans nécessitent souvent très peu de travail supplémentaire pour offrir une expérience utilisateur optimale dans une voiture.

Comme pour les grands écrans, il existe également des niveaux de qualité pour les applications dans les voitures :

  • Niveau 3 - Adaptée aux voitures : votre application est compatible avec les grands écrans et peut être utilisée lorsque la voiture est à l'arrêt. Même si elle ne dispose pas de fonctionnalités optimisées pour les voitures, les utilisateurs peuvent l'utiliser comme sur n'importe quel autre appareil Android à grand écran. Les applications mobiles qui répondent à ces exigences peuvent être distribuées telles quelles aux voitures via le programme Applications mobiles adaptées aux voitures.
  • Niveau 2 - Optimisée pour les voitures : votre application offre une expérience utilisateur optimale sur l'écran central de la voiture. Pour ce faire, votre application doit être conçue spécifiquement pour la voiture, afin d'inclure des fonctionnalités utilisables en mode conduite ou à l'arrêt, selon la catégorie de votre application.
  • Niveau 1 - Différenciée pour les voitures : votre application est conçue pour fonctionner sur différents types de matériel dans les voitures et peut adapter son expérience en mode conduite ou à l'arrêt. Offrant la meilleure expérience utilisateur, elle est conçue pour les différents écrans des voitures, tels que la console centrale, le cluster d'instruments et les écrans supplémentaires (comme les écrans panoramiques que l'on trouve dans de nombreuses voitures haut de gamme).

Dans cet atelier de programmation, vous allez implémenter l'audio pendant la conduite, qui est une fonctionnalité de niveau 1. L'application devient alors une application différenciée pour les voitures.

4. Exécuter l'application dans l'émulateur Android Automotive OS

Installer les images système Automotive avec Play Store

  1. Pour commencer, ouvrez SDK Manager dans Android Studio et sélectionnez l'onglet SDK Platforms (Plates-formes de SDK) si ce n'est pas déjà fait. En bas à droite de la fenêtre SDK Manager, assurez-vous que la case Show package details (Afficher les détails du package) est cochée.
  2. Installez l'une des images d'émulateur Android Automotive de l'API 34 répertoriées dans Ajouter des images système génériques. Les images ne s'exécutent que sur les machines disposant de la même architecture (x86/ARM).

Créer un appareil virtuel Android pour Android Automotive OS

  1. Après avoir ouvert le gestionnaire d'appareils, sélectionnez Automotive (Automobile) dans la colonne Category (Catégorie) à gauche de la fenêtre. Sélectionnez ensuite le profil matériel groupé Automotive (1408p landscape) (Automobile [paysage 1408 p]) dans la liste, puis cliquez sur Next (Suivant).

6a32a01404a7729f.png

  1. Sur la page suivante, sélectionnez l'image système de l'étape précédente. Cliquez sur Next (Suivant), sélectionnez les options avancées de votre choix, puis créez l'AVD en cliquant sur Finish (Terminer).

Exécuter l'application

Exécutez l'application sur l'émulateur que vous venez de créer en utilisant la configuration d'exécution app. Testez le comportement de l'application en accédant à l'écran du lecteur et en simulant la conduite.

5. Détecter la prise en charge de l'audio pendant la conduite

Étant donné que l'audio pendant la conduite n'est pas compatible avec tous les véhicules, vous devez détecter si l'appareil actuel est compatible avec cette fonctionnalité et adapter le comportement de votre application en conséquence. Pour ce faire, vous pouvez utiliser la classe CarFeatures de la bibliothèque androidx.car.app:app.

  1. Ajouter une dépendance à l'artefact androidx.car.app:app.

libs.version.toml

[versions]
...
carApp = "1.7.0-rc01"


[libraries]
...
androidx-car-app = { group = "androidx.car.app", name = "app", version.ref = "carApp" }

build.gradle.kts (Module :app)

implementation(libs.androidx.car.app)
  1. Dans RoadReelsPlayer, vous pouvez ensuite déterminer si la fonctionnalité est compatible et mettre à jour la logique utilisée pour calculer la valeur de shouldPreventPlay.

RoadReelsPlayer.kt

if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
    ...

    val isBackgroundAudioWhileDrivingSupported = CarFeatures.isFeatureEnabled(
        context,
        CarFeatures.FEATURE_BACKGROUND_AUDIO_WHILE_DRIVING
    )

    shouldPreventPlay = !isBackgroundAudioWhileDrivingSupported &&
            carUxRestrictionsManager.currentCarUxRestrictions.isRequiresDistractionOptimization
    invalidateState()

    carUxRestrictionsManager.registerListener { carUxRestrictions: CarUxRestrictions ->
        shouldPreventPlay = !isBackgroundAudioWhileDrivingSupported &&
            carUxRestrictions.isRequiresDistractionOptimization
        ...
    }
}

Exécutez à nouveau l'application avec ces modifications et simulez la conduite. Notez que la lecture audio se poursuit lorsque l'interface utilisateur de l'application est masquée par le système. Toutefois, ce n'est pas encore terminé. Pour répondre à toutes les exigences, vous devez apporter quelques modifications supplémentaires.

6. Prise en charge de la lecture en arrière-plan

Actuellement, la lecture des contenus multimédias de l'application est gérée par une activité. Par conséquent, la lecture des contenus multimédias peut se poursuivre pendant une courte période après l'activation des restrictions d'expérience utilisateur et le masquage de l'activité, mais votre application sera mise en cache par le système, ce qui mettra fin à la lecture.

Pour permettre la lecture sur une longue durée, l'application doit être mise à jour afin d'utiliser un service pour gérer la lecture. Pour ce faire, utilisez Media3 MediaSessionService.

Créer un MediaSessionService

  1. Effectuez un clic droit sur le package com.example.android.cars.roadreels dans la fenêtre du projet, puis sélectionnez New > Kotlin Class/File (Nouveau > Classe/Fichier Kotlin). Saisissez PlaybackService comme nom de fichier, puis cliquez sur le type Class.
  2. Ajoutez l'implémentation suivante de PlaybackService.. Consultez la section Lecture en arrière-plan avec MediaSessionService pour en savoir plus sur MediaSessionService.

PlaybackService.kt

import androidx.media3.common.util.UnstableApi
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService

@UnstableApi
class PlaybackService : MediaSessionService() {
    private var mediaSession: MediaSession? = null

    override fun onCreate() {
        super.onCreate()
        val player = RoadReelsPlayer(this)
        mediaSession = MediaSession.Builder(this, player).build()
    }

    override fun onDestroy() {
        mediaSession?.run {
            player.release()
            release()
            mediaSession = null
        }
        super.onDestroy()
    }

    override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? {
        if (controllerInfo.isTrusted || controllerInfo.packageName == packageName) {
            return mediaSession
        }
        return null
    }
}
  1. Ajoutez les éléments <uses-permission> suivants dans le fichier manifeste. La lecture des contenus multimédias est gérée à l'aide d'un service de premier plan.

AndroidManifest.xml

<manifest ...>
    ...
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
    ...
</manifest>
  1. Déclarez également le PlaybackService dans le fichier manifeste :

AndroidManifest.xml

<application ...>
    ...
    <service
        android:name=".PlaybackService"
        android:foregroundServiceType="mediaPlayback"
        android:exported="true">
        <intent-filter>
            <action android:name="androidx.media3.session.MediaSessionService"/>
        </intent-filter>
    </service>
</application>

Mettre à jour le PlayerViewModel pour utiliser le PlaybackService

  1. Étant donné que le PlaybackService crée et expose une MediaSession, il n'est plus nécessaire que le PlayerViewModel en crée une. Recherchez et supprimez la ligne suivante ainsi que toutes les références à la variable :

PlayerViewModel.kt

private var mediaSession: MediaSession? = null
  1. Remplacez ensuite la section du bloc init qui instancie un RoadReelsPlayer par le code suivant, qui connecte l'application au PlaybackService à l'aide d'un MediaController.

PlayerViewModel.kt

import android.content.ComponentName
import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken
import com.example.android.cars.roadreels.PlaybackService
import com.google.common.util.concurrent.MoreExecutors

...

init {
        viewModelScope.launch {
            ...
        }
        
        val sessionToken = SessionToken(
            application,
            ComponentName(application, PlaybackService::class.java)
        )

        val mediaControllerFuture =
            MediaController.Builder(getApplication(), sessionToken).buildAsync()

        mediaControllerFuture.addListener(
            { _player.update { mediaControllerFuture.get() } },
            MoreExecutors.directExecutor()
        )
    }

Testez à nouveau l'application. Une autre interface utilisateur devrait s'afficher lorsque l'application est bloquée par le système. L'utilisateur peut désormais contrôler la lecture lorsqu'il conduit. Une fois à nouveau à l'arrêt, il peut cliquer sur le bouton de sortie pour revenir à l'interface complète de l'application.

33eb8ff3d4035978.gif

Supprimer les modifications de lecture du cycle de vie

Puisque la lecture en arrière-plan est désormais prise en charge, vous pouvez supprimer les deux blocs LifecycleEventEffect dans PlayerScreen.kt pour que la lecture puisse se poursuivre lorsque l'utilisateur quitte l'application, y compris lorsque les commandes de lecture affichées à l'écran précédent sont visibles.

Mettre en pause la lecture lorsque l'utilisateur quitte l'écran du lecteur

Étant donné que le lecteur (qui est maintenant contenu dans le PlaybackService) n'est pas libéré lorsque vous quittez l'écran du lecteur, vous devez ajouter un appel pour mettre en pause la lecture lorsque vous quittez l'écran, afin de conserver le comportement précédent. Pour ce faire, vous pouvez mettre à jour l'implémentation de la méthode onCleared du PlayerViewModel :

PlayerViewModel.kt

override fun onCleared() {
    super.onCleared()
    _player.value?.apply {
        pause()
        release()
    }
}

7. Mettre à jour le fichier manifeste

Enfin, pour indiquer que votre application est compatible avec l'audio en conduisant, vous devez ajouter l'élément <uses-feature> suivant dans le fichier manifeste de votre application.

AndroidManifest.xml

<application>
    <uses-feature android:name="com.android.car.background_audio_while_driving" android:required="false">
</application>

8. Félicitations

Vous avez réussi à ajouter la compatibilité avec l'audio pendant la conduite à une application vidéo. Il est maintenant temps d'appliquer ce que vous avez appris à votre propre application.

Complément d'informations