Intégrer des raccourcis dynamiques à l'Assistant Google grâce aux actions dans l'application

1. Présentation

Dans l'atelier de programmation précédent, vous avez utilisé des raccourcis statiques pour implémenter des intents intégrés couramment utilisés dans une application exemple. Les développeurs Android utilisent les actions dans les applications pour intégrer les fonctionnalités de l'application à l'Assistant Google.

Les raccourcis statiques sont regroupés avec une application et ne peuvent être modifiés qu'en publiant de nouvelles versions de celle-ci. Si vous souhaitez activer des fonctionnalités vocales pour les éléments dynamiques dans une application, comme le contenu généré par l'utilisateur, vous devez utiliser des raccourcis dynamiques. Les applications envoient des raccourcis dynamiques lorsque les utilisateurs effectuent certaines actions, comme créer une note dans une application de suivi des tâches. Avec les actions dans les applications, vous activez ces raccourcis vocaux en les associant à un intent intégré, ce qui permet aux utilisateurs d'accéder à leur contenu à partir de l'Assistant en disant, par exemple, "Hey Google, ouvre ma liste de courses sur ExampleApp".

Trois écrans progressifs sur lesquels l'Assistant Google lance un raccourci dynamique.

Figure 1. Trois écrans progressifs montrant une tâche créée par l'utilisateur et l'Assistant Google qui lance un raccourci dynamique sur cette tâche.

Objectifs de l'atelier

Dans cet atelier de programmation, vous allez activer des raccourcis dynamiques pour les commandes vocales dans une application Android exemple permettant de dresser des listes de tâches. Les utilisateurs pourront ainsi demander à l'Assistant d'ouvrir les éléments de la liste qu'ils créent dans l'application. Pour ce faire, vous utilisez des modèles d'architecture Android, en particulier repository, service locator et ViewModel.

Conditions préalables

Cet atelier de programmation s'appuie sur les concepts des actions dans l'application abordés dans l'atelier de programmation précédent, en particulier les intents intégrés et les raccourcis statiques. Si vous ne connaissez pas les actions dans les applications, nous vous recommandons de suivre l'atelier de programmation à leur sujet avant de continuer.

Vérifiez également que la configuration de votre environnement de développement dispose des éléments de configuration suivants :

  • Un terminal permettant d'exécuter des commandes shell et avec git installé
  • La dernière version stable d'Android Studio
  • Un appareil Android physique ou virtuel connecté à Internet
  • Un compte Google connecté à Android Studio, à l'appli Google et à l'application Assistant Google

2. Principes de fonctionnement

Pour activer un raccourci dynamique avec Voice Access, vous devrez :

Lier des raccourcis

Pour qu'un raccourci dynamique soit accessible depuis l'Assistant, il doit être lié à un intent intégré. Lorsqu'un intent intégré avec un raccourci est déclenché, l'Assistant associe les paramètres de la requête utilisateur aux mots clés définis dans le raccourci lié. Exemple :

  • Un raccourci lié à l'intent intégré GET_THING pourrait permettre aux utilisateurs de demander un contenu spécifique dans l'application directement à l'Assistant. * "Hey Google, ouvre ma liste de courses sur ExampleApp."
  • Un raccourci lié à l'intent intégré ORDER_MENU_ITEM pourrait permettre aux utilisateurs de répéter les commandes précédentes. * "Hey Google, commande ce que je prends d'habitude chez ExampleApp."

Consultez la documentation de référence sur les intents intégrés pour obtenir la liste complète des intents intégrés classés par catégorie.

Fournir des raccourcis à l'Assistant

Après avoir lié vos raccourcis à un intent intégré, l'étape suivante consiste à autoriser l'Assistant à ingérer ces raccourcis en ajoutant la bibliothèque d'intégration des raccourcis Google à votre projet. Une fois cette bibliothèque en place, l'Assistant connaîtra tous les raccourcis transmis par votre application. Les utilisateurs pourront alors lancer ces raccourcis grâce à l'expression de déclenchement du raccourci dans l'Assistant.

3. Préparer votre environnement de développement

Cet atelier de programmation utilise une application exemple pour Android permettant de dresser liste de tâches conçue. Cette application permet aux utilisateurs d'ajouter des éléments à des listes, de faire des recherches par catégorie et de les filtrer par état. Téléchargez et préparez l'application exemple en remplissant cette section.

Télécharger vos fichiers de base

Exécutez la commande suivante pour cloner le dépôt GitHub de l'exemple d'application :

git clone https://github.com/actions-on-google/app-actions-dynamic-shortcuts.git

Une fois le dépôt cloné, procédez comme suit pour l'ouvrir dans Android Studio :

  1. Dans la boîte de dialogue Welcome to Android Studio (Bienvenue dans Android Studio), cliquez sur Import project (Importer un projet).
  2. Sélectionnez le dossier dans lequel vous avez cloné le dépôt.

Vous pouvez également afficher une version de l'application exemple telle qu'elle est à la fin de l'atelier de programmation en clonant la branche codelab-complete de son dépôt GitHub :

git clone https://github.com/actions-on-google/app-actions-dynamic-shortcuts.git --branch codelab-complete

Modifier l'ID d'application Android

Modifier l'ID de l'application permet d'identifier de manière unique l'application sur votre appareil de test et d'éviter une erreur "Duplicate package name" (Nom de package en double) si l'application est importée dans la Play Console. Pour modifier l'ID application, ouvrez app/build.gradle :

android {
...
  defaultConfig {
    applicationId "com.MYUNIQUENAME.android.fitactions"
    ...
  }
}

Dans le champ applicationId, remplacez "MYUNIQUENAME" par un nom qui vous est propre.

Ajouter les dépendances de l'API Shortcuts

Ajoutez les bibliothèques Jetpack suivantes au fichier de ressources app/build.gradle :

app/build.gradle

dependencies {
   ...
   // Shortcuts library
   implementation "androidx.core:core:1.6.0"
   implementation 'androidx.core:core-google-shortcuts:1.0.1'
   ...
}

Tester l'application sur votre appareil

Avant d'apporter d'autres modifications au code de l'application, il peut être utile de la tester pour vous faire une idée de ses fonctionnalités. Pour exécuter l'application sur votre émulateur, procédez comme suit :

  1. Dans Android Studio, sélectionnez "Run" > "Run app" (Exécuter > Exécuter l'application) ou cliquez sur Run Icône Exécuter l'application dans Android Studio (Exécuter) dans la barre d'outils.
  2. Dans la boîte de dialogue Select Deployment Target (Sélectionner une cible de déploiement), sélectionnez un appareil, puis cliquez sur OK. La version d'OS recommandée est Android 10 (niveau d'API 30) ou version ultérieure, bien que les actions dans l'application fonctionnent sur des appareils à partir d'Android 5 (niveau d'API 21).
  3. Appuyez de manière prolongée sur le bouton Accueil pour configurer l'Assistant et vérifier qu'il fonctionne. Vous devrez vous connecter à l'Assistant sur votre appareil si ce n'est pas déjà fait.

Pour en savoir plus sur les appareils virtuels Android, consultez Créer et gérer des appareils virtuels.

Parcourez l'application pour voir ses fonctionnalités. Appuyez sur l'icône Plus pour créer une tâche. Les éléments de menu en haut à droite vous permettent de rechercher et de filtrer les tâches par état.

4. Créer une classe de dépôt de raccourcis

Plusieurs classes de notre application exemple appelleront l'API ShortcutManagerCompat pour transférer et gérer des raccourcis dynamiques. Afin de réduire la redondance du code, vous allez implémenter un dépôt permettant à vos classes de projet de gérer facilement les raccourcis dynamiques.

Le modèle de conception du dépôt fournit une API propre pour gérer les raccourcis. Utiliser un dépôt permet aux détails de l'API sous-jacente d'être éliminés de manière uniforme derrière une API minimale. Implémentez le dépôt comme suit :

  1. Créez une classe ShortcutsRepository pour éliminer l'API ShortcutManagerCompat.
  2. Ajoutez des méthodes ShortcutsRepository à l'outil de localisation de services de l'application.
  3. Enregistrez le service ShortcutRepository dans l'application principale.

Créer le dépôt

Créez une classe Kotlin nommée ShortcutsRepository dans le package com.example.android.architecture.blueprints.todoapp.data.source. Il se trouve dans le dossier app/src/main/java. Vous allez implémenter dans cette classe une interface fournissant un ensemble réduit de méthodes couvrant notre cas d'utilisation de l'atelier de programmation.

Fenêtre Android Studio affichant l'emplacement de la classe ShortcutsRepository.

Figure 2. Fenêtre "Fichiers de projet" d'Android Studio affichant l'emplacement de la classe ShortcutsRepository.

Collez le code suivant dans la nouvelle classe :

package com.example.android.architecture.blueprints.todoapp.data.source

import android.content.Context
import android.content.Intent
import androidx.annotation.WorkerThread
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import com.example.android.architecture.blueprints.todoapp.data.Task
import com.example.android.architecture.blueprints.todoapp.tasks.TasksActivity

private const val GET_THING_KEY = "q"

/**
* ShortcutsRepository provides an interface for managing dynamic shortcuts.
*/
class ShortcutsRepository(val context: Context) {

   private val appContext = context.applicationContext

   /**
    * Pushes a dynamic shortcut. The task ID is used as the shortcut ID.
    * The task's title and description are used as shortcut's short and long labels.
    * The resulting shortcut corresponds to the GET_THING capability with task's
    * title used as BII's "name" argument.
    *
    * @param task Task object for which to create a shortcut.
    */
   @WorkerThread
   fun pushShortcut(task: Task) {
      // TODO
   }

   private fun createShortcutCompat(task: Task): ShortcutInfoCompat {
      //...
   }

   /**
    *  Updates a dynamic shortcut for the provided task. If the shortcut
    *  associated with this task doesn't exist, this method throws an error.
    *  This operation may take a few seconds to complete.
    *
    * @param tasks list of tasks to update.
    */
   @WorkerThread
   fun updateShortcuts(tasks: List<Task>) {
       //...
   }

   /**
    * Removes shortcuts if IDs are known.
    *
    * @param ids list of shortcut IDs
    */
   @WorkerThread
   fun removeShortcutsById(ids: List<String>) {
       //...
   }

   /**
    * Removes shortcuts associated with the tasks.
    *
    * @param tasks list of tasks to remove.
    */
   @WorkerThread
   fun removeShortcuts(tasks: List<Task>) {
       //...
   }
}

Ensuite, modifiez la méthode pushShortcut pour appeler l'API ShortcutManagerCompat. Remplacez la classe ShortcutsRepository avec le code suivant :

ShortcutsRepository.kt

/**
* Pushes a dynamic shortcut for the task. The task's ID is used as a shortcut
* ID. The task's title and description are used as shortcut's short and long
* labels. The created shortcut corresponds to GET_THING capability with task's
* title used as BII's "name" argument.
*
* @param task Task object for which to create a shortcut.
*/

@WorkerThread
fun pushShortcut(task: Task) {
   ShortcutManagerCompat.pushDynamicShortcut(appContext, createShortcutCompat(task))
}

Dans l'exemple de code précédent, nous avons transmis appContext à l'API. Il s'agit d'une propriété de classe contenant un contexte d'application. Il est important d'utiliser un contexte d'application (par opposition à un contexte d'activité) pour éviter les fuites de mémoire. En effet, le contexte peut être conservé plus longtemps que le cycle de vie de l'activité de l'hôte.

De plus, l'API nécessite la transmission d'un objet ShortcutInfoCompat pour l'objet Task. Dans l'exemple de code précédent, nous effectuons cette opération en appelant la méthode privée createShortcutCompat, que nous allons modifier pour créer et renvoyer un objet ShortcutInfoCompat. Pour ce faire, modifiez le bouchon createShortcutCompat avec le code suivant :

ShortcutsRepository.kt

private fun createShortcutCompat(task: Task): ShortcutInfoCompat {
   val intent = Intent(appContext, TasksActivity::class.java)
   intent.action = Intent.ACTION_VIEW
   // Filtering is set based on currentTitle.
   intent.putExtra(GET_THING_KEY, task.title)

   // A unique ID is required to avoid overwriting an existing shortcut.
   return ShortcutInfoCompat.Builder(appContext, task.id)
           .setShortLabel(task.title)
           .setLongLabel(task.title)
           // Call addCapabilityBinding() to link this shortcut to a BII. Enables user to invoke a shortcut using its title in Assistant.
           .addCapabilityBinding(
                   "actions.intent.GET_THING", "thing.name", listOf(task.title))
           .setIntent(intent)
           .setLongLived(false)
       .build()
}

Les bouchons de fonction restants de cette classe concernent la modification et la suppression des raccourcis dynamiques. Pour activer ces fonctions, utilisez le code suivant :

ShortcutsRepository.kt

/**
* Updates a Dynamic Shortcut for the task. If the shortcut associated with this task
* doesn't exist, throws an error. This operation may take a few seconds to complete.
*
* @param tasks list of tasks to update.
*/
@WorkerThread
fun updateShortcuts(tasks: List<Task>) {
   val scs = tasks.map { createShortcutCompat(it) }
   ShortcutManagerCompat.updateShortcuts(appContext, scs)
}

/**
* Removes shortcuts if IDs are known.
* @param ids list of shortcut IDs
*/
@WorkerThread
fun removeShortcutsById(ids: List<String>) {
   ShortcutManagerCompat.removeDynamicShortcuts(appContext, ids)
}

/**
* Removes shortcuts associated with the tasks.
*
* @param tasks list of tasks to remove.
*/
@WorkerThread
fun removeShortcuts(tasks: List<Task>) {
   ShortcutManagerCompat.removeDynamicShortcuts (appContext,
           tasks.map { it.id })
}

Ajouter une classe à l'outil de localisation de services

Une fois la classe ShortcutsRepository créée, l'étape suivante consiste à mettre les objets instanciés de cette classe à la disposition du reste de l'application. Cette application gère les dépendances de classe en implémentant le modèle de localisation de services. Ouvrez la classe de l'outil de localisation de services à l'aide du navigateur de classe dans Android Studio. Pour ce faire, accédez à Navigate > Class (Naviguer > Classe) et saisissez "ServiceLocator". Cliquez sur le fichier Kotlin obtenu pour l'ouvrir dans votre IDE.

En haut de ServiceLocator.kt, collez le code suivant pour importer les packages ShortcutsRepository et SuppressLint :

ServiceLocator.kt

package com.example.android.architecture.blueprints.todoapp

// ...Other import statements
import com.example.android.architecture.blueprints.todoapp.data.source.ShortcutsRepository
import android.annotation.SuppressLint

Ajoutez les méthodes et les membres du service ShortcutRepository en collant le code suivant dans le corps de ServiceLocator.kt :

ServiceLocator.kt

object ServiceLocator {

   // ...
   // Only the code immediately below this comment needs to be copied and pasted
   // into the body of ServiceLocator.kt:

   @SuppressLint("StaticFieldLeak")
   @Volatile
   var shortcutsRepository: ShortcutsRepository? = null

   private fun createShortcutsRepository(context: Context): ShortcutsRepository {
       val newRepo = ShortcutsRepository(context.applicationContext)
       shortcutsRepository = newRepo
       return newRepo
   }

   fun provideShortcutsRepository(context: Context): ShortcutsRepository {
       synchronized(this) {
           return shortcutsRepository ?: shortcutsRepository ?: createShortcutsRepository(context)
       }
   }
 }

Enregistrer le service de raccourcis

La dernière étape consiste à enregistrer votre nouveau service ShortcutsRepository auprès de l'application. Dans Android Studio, ouvrez TodoApplication.kt et copiez le code suivant en haut du fichier :

TodoApplication.kt

package com.example.android.architecture.blueprints.todoapp
/// ... Other import statements

import com.example.android.architecture.blueprints.todoapp.data.source.ShortcutsRepository

Ensuite, enregistrez le service en ajoutant le code suivant au corps de la classe :

TodoApplication.kt

//...
class TodoApplication : Application() {

   //...

   val shortcutsRepository: ShortcutsRepository
       get() = ServiceLocator.provideShortcutsRepository(this)

   //...
}

Créez l'application et vérifiez qu'elle continue de fonctionner.

5. Transmettre un nouveau raccourci

Une fois votre service de raccourcis créé, vous pouvez commencer à transmettre les raccourcis. Étant donné que les utilisateurs génèrent du contenu (tâches) dans cette application et s'attendent à pouvoir y accéder ultérieurement, nous allons activer l'accès à ce contenu par commande vocale. Pour ce faire, nous allons transférer un raccourci dynamique associé à l'intent intégré GET_THING chaque fois qu'un utilisateur crée une tâche. Cela permet à l'Assistant de rediriger les utilisateurs directement vers la tâche demandée lorsqu'ils déclenchent l'intent intégré en disant, par exemple, "Hey Google, ouvre ma liste de courses sur SampleApp".

Pour activer cette fonctionnalité dans l'application exemple, procédez comme suit :

  1. Importez le service ShortcutsRepository dans la classe AddEditTaskViewModel, qui sert à gérer les objets de la liste de tâches.
  2. Transférez un raccourci dynamique lorsque l'utilisateur crée une tâche.

Importer ShortcutsRepository

Nous devons d'abord mettre le service ShortcutsRepository à la disposition de AddEditTaskViewModel. Pour ce faire, importez le service vers ViewModelFactory. Il s'agit de la classe d'usine utilisée par l'application pour instancier des objets ViewModel, y compris AddEditTaskViewModel.

Ouvrez le navigateur de classe dans Android Studio en accédant à Navigate > Class (Naviguer > Classe), puis saisissez "ViewModelFactory". Cliquez sur le fichier Kotlin obtenu pour l'ouvrir dans votre IDE.

En haut de ViewModelFactory.kt, collez le code suivant pour importer les packages ShortcutsRepository et SuppressLint :

ViewModelFactory.kt

package com.example.android.architecture.blueprints.todoapp

// ...Other import statements
import com.example.android.architecture.blueprints.todoapp.data.source.ShortcutsRepository

Ensuite, remplacez le corps de ViewModelFactory par le code suivant :

ViewModelFactory.kt

/**
 * Factory for all ViewModels.
 */
@Suppress("UNCHECKED_CAST")
class ViewModelFactory constructor(
    private val tasksRepository: TasksRepository,
    private val shortcutsRepository: ShortcutsRepository,
    owner: SavedStateRegistryOwner,
    defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {

    override fun <T : ViewModel> create(
        key: String,
        modelClass: Class<T>,
        handle: SavedStateHandle
    ) = with(modelClass) {
        when {
            isAssignableFrom(StatisticsViewModel::class.java) ->
                StatisticsViewModel(tasksRepository)
            isAssignableFrom(TaskDetailViewModel::class.java) ->
                TaskDetailViewModel(tasksRepository)
            isAssignableFrom(AddEditTaskViewModel::class.java) ->
                AddEditTaskViewModel(tasksRepository, shortcutsRepository)
            isAssignableFrom(TasksViewModel::class.java) ->
                TasksViewModel(tasksRepository, handle)
            else ->
                throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
        }
    } as T
}

Finalisez les modifications de ViewModelFactory en remontant d'une couche et transmettez ShortcutsRepository au constructeur de la fabrique. Ouvrez l'explorateur de fichiers d'Android Studio en accédant à Navigate > File (Navigation > Fichier), puis en saisissant "FragmentExt.kt". Cliquez sur le fichier Kotlin obtenu dans le package util pour l'ouvrir dans votre IDE.

Remplacez le corps de FragmentExt.kt par le code suivant :

fun Fragment.getViewModelFactory(): ViewModelFactory {
   val taskRepository = (requireContext().applicationContext as TodoApplication).taskRepository
   val shortcutsRepository = (requireContext().applicationContext as TodoApplication).shortcutsRepository
   return ViewModelFactory(taskRepository, shortcutsRepository, this)
}

Utiliser un raccourci

Avec la classe d'abstraction ShortcutsRepository disponible pour les classes ViewModel de l'application exemple, vous modifiez AddEditTaskViewModel (la classe ViewModel chargée de créer des notes) afin d'envoyer un raccourci dynamique chaque fois qu'un utilisateur crée une note.

Dans Android Studio, ouvrez le navigateur de classe, puis saisissez "AddEditTaskViewModel". Cliquez sur le fichier Kotlin obtenu pour l'ouvrir dans votre IDE.

D'abord, ajoutez le package ShortcutsRepository à cette classe avec l'instruction d'importation suivante :

package com.example.android.architecture.blueprints.todoapp.addedittask

//Other import statements
import com.example.android.architecture.blueprints.todoapp.data.source.ShortcutsRepository

Ensuite, ajoutez la propriété de classe shortcutsRepository en remplaçant le constructeur de la classe par le code suivant :

AddEditTaskViewModel.kt

//...

/**
* ViewModel for the Add/Edit screen.
*/
class AddEditTaskViewModel(
   private val tasksRepository: TasksRepository,
   private val shortcutsRepository: ShortcutsRepository
) : ViewModel() {

    //...

Une fois la classe ShortcutsRepository ajoutée, créez une fonction, pushShortcut(), pour appeler cette classe. Collez la fonction privée suivante dans le corps de AddEditTaskViewModel :

AddEditTaskViewModel.kt

//...
private fun pushShortcut(newTask: Task) = viewModelScope.launch {
   shortcutsRepository.pushShortcut(newTask)
}

Enfin, transmettez un nouveau raccourci dynamique chaque fois qu'une tâche est créée. Remplacez le contenu de la fonction saveTask() par le code suivant :

AddEditTaskViewModel.kt

fun saveTask() {
    val currentTitle = title.value
    val currentDescription = description.value

    if (currentTitle == null || currentDescription == null) {
        _snackbarText.value = Event(R.string.empty_task_message)
        return
    }
    if (Task(currentTitle, currentDescription).isEmpty) {
        _snackbarText.value = Event(R.string.empty_task_message)
        return
    }

    val currentTaskId = taskId
    if (isNewTask || currentTaskId == null) {
        val task = Task(currentTitle, currentDescription)
        createTask(task)
        pushShortcut(task)
    } else {
        val task = Task(currentTitle, currentDescription, taskCompleted, currentTaskId)
        updateTask(task)
    }
}

Tester votre code

Nous sommes enfin prêts à tester notre code. Au cours de cette étape, vous allez transmettre un raccourci dynamique à commande vocale et l'inspecter à l'aide de l'application Assistant Google.

Créer un aperçu

Lorsque vous créez un aperçu à l'aide du plug-in Assistant Google, vos raccourcis dynamiques apparaissent dans l'Assistant sur votre appareil de test.

Installer le plug-in de test

Si vous n'avez pas encore installé le plug-in Assistant Google, accédez à Android Studio et procédez comme suit :

  1. Accédez à **File > Settings (Fichier > Paramètres), ou à Android Studio > Preferences (Android Studio > Préférences) sous macOS.
  2. Dans la section Plugins (Plug-ins), accédez à Marketplace et recherchez "Google Assistant" (Assistant Google).
  3. Installez l'outil, puis redémarrez Android Studio.

Créer l'aperçu

Pour créer un aperçu, accédez à Android Studio et procédez comme suit :

  1. Cliquez sur Tools > Google Assistant > "App Actions Test Tool" (Outils > Assistant Google > Outil de test des actions dans l'application).
  2. Dans le champ App name (nom de l'application), saisissez un nom (par exemple, "Liste de tâches").
  3. Cliquez sur Create Preview (Créer un aperçu). Si vous y êtes invité, lisez et acceptez les règles et les conditions d'utilisation des actions dans les applications.

Volet de création d'aperçu de l'outil de test des actions dans l'application.

Figure 3. Volet de création d'aperçu de l'outil de test des actions dans l'application.

Pendant le test, les raccourcis dynamiques que vous transmettez à l'Assistant y figureront classés selon le nom de l'application que vous avez fourni pour l'aperçu.

Transmettre et inspecter un raccourci

Relancez l'application exemple sur votre appareil de test, puis procédez comme suit :

  1. Créez une tâche intitulée "Démarrer l'atelier de programmation".
  2. Ouvrez l'application Assistant Google et dites ou saisissez "Mes raccourcis".
  3. Appuyez sur l'onglet Explore (Explorer) : l'exemple de raccourci devrait s'afficher.
  4. Appuyez sur le raccourci pour l'appeler. L'application devrait se lancer avec le nom du raccourci inséré dans la zone de filtre, ce qui facilite la recherche de l'élément de tâche demandé.

6. (Facultatif) Modifier et supprimer un raccourci

En plus de pouvoir transmettre de nouveaux raccourcis dynamiques au moment de l'exécution, votre application peut les modifier pour refléter l'état actuel du contenu et des préférences de l'utilisateur. Il est recommandé de modifier les raccourcis existants chaque fois qu'un utilisateur change l'élément de destination (par exemple, en renommant une tâche dans l'application exemple). De même, lorsqu'une ressource de destination est supprimée, vous devez supprimer le raccourci correspondant afin d'empêcher les raccourcis non fonctionnels d'être présentés à l'utilisateur.

Modifier un raccourci

Apportez des changements à AddEditTaskViewModel pour modifier un raccourci dynamique chaque fois qu'un utilisateur modifie les détails d'un élément de tâche. Tout d'abord, remplacez le corps de la classe par le code suivant pour ajouter une fonction de modification utilisant notre classe de dépôt :

AddEditTaskViewModel.kt

private fun updateShortcut(newTask: Task) = viewModelScope.launch {
   shortcutsRepository.updateShortcuts(listOf(newTask))
}

Modifiez ensuite la fonction saveTask() pour appeler notre nouvelle méthode chaque fois qu'une tâche existante est modifiée.

AddEditTaskViewModel.kt

// Called when clicking on fab.
fun saveTask() {
   // ...
   // Note: the shortcuts are created/updated in a worker thread.
   if (isNewTask || currentTaskId == null) {
       //...
   } else {
       //...
       updateShortcut(task)
   }
}

Testez votre code en redémarrant l'application et en procédant comme suit :

  1. Renommez le titre de votre tâche existante "Terminer l'atelier de programmation".
  2. Ouvrez l'Assistant Google en disant "Hey Google, mes raccourcis".
  3. Appuyez sur l'onglet Explore (Explorer) : vous devriez voir un nouveau libellé pour votre raccourci de test.

Supprimer un raccourci

Lorsque l'utilisateur retire une tâche, les raccourcis correspondants doivent être supprimés. Dans l'application, la logique de suppression des tâches se trouve dans la classe TaskDetailViewModel. Avant d'apporter des changements cette classe, nous devons à nouveau modifier ViewModelFactory afin de transmettre shortcutsRepository dans TaskDetailViewModel.

Ouvrez ViewModelFactory et remplacez le contenu de la méthode constructeur par le code suivant :

//...
class ViewModelFactory constructor(
       private val tasksRepository: TasksRepository,
       private val shortcutsRepository: ShortcutsRepository,
       owner: SavedStateRegistryOwner,
       defaultArgs: Bundle? = null
) : AbstractSavedStateViewModelFactory(owner, defaultArgs) {

   override fun <T : ViewModel> create(
           key: String,
           modelClass: Class<T>,
           handle: SavedStateHandle
   ) = with(modelClass) {
       when {
           isAssignableFrom(StatisticsViewModel::class.java) ->
               StatisticsViewModel(tasksRepository)
           isAssignableFrom(TaskDetailViewModel::class.java) ->
               TaskDetailViewModel(tasksRepository, shortcutsRepository)
           isAssignableFrom(AddEditTaskViewModel::class.java) ->
               AddEditTaskViewModel(tasksRepository, shortcutsRepository)
           isAssignableFrom(TasksViewModel::class.java) ->
               TasksViewModel(tasksRepository, handle)
           else ->
               throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
       }
   } as T
}

Ensuite, ouvrez TaskDetailViewModel. Importez le module ShortcutsRepository et déclarez une variable d'instance pour celui-ci à l'aide du code suivant :

TaskDetailViewModel.kt

package com.example.android.architecture.blueprints.todoapp.taskdetail

...
import com.example.android.architecture.blueprints.todoapp.data.source.ShortcutsRepository

/**
* ViewModel for the Details screen.
*/
class TaskDetailViewModel(
       //...
       private val shortcutsRepository: ShortcutsRepository
   ) : ViewModel() {
...
}

Enfin, modifiez la fonction deleteTask() pour appeler shortcutsRepository afin de supprimer un raccourci basé sur son ID chaque fois qu'une tâche avec un taskId correspondant est supprimée :

TaskDetailViewModel.kt

fun deleteTask() = viewModelScope.launch {
   _taskId.value?.let {
       //...
       shortcutsRepository.removeShortcutsById(listOf(it))
   }
}

Pour tester votre code, relancez l'application et procédez comme suit :

  1. Supprimez votre tâche de test.
  2. Renommez le titre de votre tâche existante "Terminer l'atelier de programmation".
  3. Ouvrez l'Assistant Google en disant "Hey Google, mes raccourcis".
  4. Appuyez sur l'onglet Explore (Explorer) : vérifiez que votre raccourci de test ne s'affiche plus.

7. Étapes suivantes

Félicitations ! Désormais, les utilisateurs de notre application exemple peuvent facilement revenir aux notes qu'ils créent grâce à l'Assistant en disant, par exemple, "Hey Google, ouvre ma liste de courses sur ExampleApp". Les raccourcis favorisent l'engagement des utilisateurs en facilitant la répétition des actions fréquemment effectuées dans votre application.

Points abordés

Dans cet atelier de programmation, vous avez appris à :

  • identifier les cas d'utilisation permettant de transmettre des raccourcis dynamiques à une application ;
  • réduire la complexité du code à l'aide des modèles de dépôt, d'injection de dépendances et de localisation de services ;
  • transmettre des raccourcis dynamiques à commande vocale dans le contenu de l'application généré par l'utilisateur ;
  • modifier et supprimer des raccourcis existants.

Étapes suivantes

À présent, vous pouvez essayer d'affiner votre application de liste de tâche. Pour référencer le projet terminé, consultez le dépôt –codelab-complete branch sur GitHub.

Voici quelques suggestions pour en savoir plus sur l'intégration d'actions dans l'application :

Pour poursuivre votre parcours Actions on Google, consultez les ressources suivantes :

Suivez-nous sur Twitter (@ActionsOnGoogle) pour connaître les dernières informations, et tweetez avec le #appActions pour montrer votre création.

Enquête

Pour terminer, veuillez répondre à cette enquête afin de nous faire part de vos commentaires sur cet atelier de programmation.