Estendi le scorciatoie dinamiche all'Assistente Google con Azioni app

1. Panoramica

Nel codelab precedente, hai utilizzato scorciatoie statiche per implementare intent integrati (BII) di uso comune in un'app di esempio. Gli sviluppatori Android utilizzano Azioni app per estendere la funzionalità dell'app all'Assistente Google.

Le scorciatoie statiche sono incluse in un'app e possono essere aggiornate solo rilasciando nuove versioni dell'app. L'attivazione della funzionalità vocale per gli elementi dinamici di un'app, ad esempio i contenuti generati dagli utenti, viene eseguita utilizzando le scorciatoie dinamiche. Le app inviano scorciatoie dinamiche dopo che gli utenti eseguono azioni pertinenti, ad esempio la creazione di una nuova nota in un'app di monitoraggio delle attività. Con le azioni app, puoi attivare queste scorciatoie per i comandi vocali associandole a un BII, in modo che gli utenti possano accedere ai propri contenuti dall'assistente dicendo, ad esempio, "Hey Google, apri la mia lista della spesa su AppEsempio".

Tre schermate progressive che mostrano l'Assistente Google che avvia una scorciatoia dinamica.

Figura 1. Tre schermate progressive che mostrano un'attività creata dall'utente e l'Assistente Google che lancia una scorciatoia dinamica per l'elemento dell'attività.

Cosa creerai

In questo codelab, abiliterai le scorciatoie dinamiche per la voce in un'app Android con un elenco di cose da fare di esempio, consentendo agli utenti di chiedere all'assistente di aprire gli elementi dell'elenco di attività che creano nell'app. Puoi farlo utilizzando i pattern di architettura Android, in particolare i pattern di repository, service locator e ViewModel.

Prerequisiti

Questo codelab si basa sui concetti delle Azioni app trattati nel codelab precedente, in particolare intent integrati e scorciatoie statiche. Se non hai mai utilizzato le Azioni app, ti consigliamo di completare questo codelab prima di continuare.

Inoltre, prima di procedere, assicurati che l'ambiente di sviluppo abbia la seguente configurazione:

  • Un terminale per eseguire i comandi della shell con Git installato.
  • L'ultima release stabile di Android Studio.
  • Un dispositivo Android fisico o virtuale con accesso a internet.
  • Un Account Google con cui è stato eseguito l'accesso ad Android Studio, all'app Google e all'app Assistente Google.

2. Come funziona

L'attivazione di una scorciatoia dinamica per l'accesso vocale prevede i seguenti passaggi:

Scorciatoie di associazione

Affinché una scorciatoia dinamica sia accessibile dall'assistente, deve essere associata a un BII pertinente. Quando viene attivato un intent integrato con una scorciatoia, l'assistente associa i parametri nella richiesta dell'utente alle parole chiave definite nella scorciatoia associata. Ad esempio:

  • Una scorciatoia associata all'intent integrato GET_THING potrebbe consentire agli utenti di richiedere contenuti in-app specifici direttamente dall'assistente. * "Hey Google, apri la mia lista della spesa su ExampleApp."
  • Una scorciatoia associata all'intent integrato START_EXERCISE potrebbe consentire agli utenti di vedere le proprie sessioni di allenamento. * "Hey Google, chiedi ad ExampleApp di avviare il mio solito allenamento."

Per un elenco completo categorizzato di intent integrati, consulta Riferimento per gli intent integrati.

Fornire scorciatoie all'assistente

Dopo aver associato le scorciatoie a un BII, il passaggio successivo consiste nell'abilitare l'assistente a importare queste scorciatoie aggiungendo la libreria Google Shortcuts Integration al progetto. Con questa libreria attiva, l'assistente sarà a conoscenza di ogni scorciatoia inviata dalla tua app, consentendo agli utenti di avviarle usando la frase di attivazione della scorciatoia nell'assistente.

3. Prepara l'ambiente di sviluppo

Questo codelab utilizza un'app di esempio per le liste di cose da fare creata per Android. Con questa app, gli utenti possono aggiungere elementi agli elenchi, cercare elementi degli elenchi di attività per categoria e filtrare le attività in base allo stato di completamento. Scaricare e preparare l'app di esempio completando questa sezione.

Scaricare i file di base

Esegui il comando seguente per clonare il repository GitHub dell'app di esempio:

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

Dopo aver clonato il repository, segui questi passaggi per aprirlo in Android Studio:

  1. Nella finestra di dialogo Ti diamo il benvenuto in Android Studio, fai clic su Importa progetto.
  2. Seleziona la cartella in cui hai clonato il repository.

In alternativa, puoi visualizzare una versione dell'app di esempio che rappresenta il codelab completato clonando il ramo codelab-complete del relativo repository GitHub:

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

Aggiornare l'ID applicazione Android

L'aggiornamento dell'ID applicazione dell'app identifica in modo univoco l'app sul dispositivo di test ed evita l'errore "Nome pacchetto duplicato" se l'app viene caricata su Play Console. Per aggiornare l'ID applicazione, apri app/build.gradle:

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

Sostituisci "MYUNIQUENAME" nel campo applicationId con un nome univoco.

Aggiungi dipendenze API Shortcuts

Aggiungi le seguenti librerie Jetpack al file di risorse 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'
   ...
}

Testa l'app sul tuo dispositivo

Prima di apportare altre modifiche all'app, è utile farsi un'idea di cosa può fare l'app di esempio. Per eseguire l'app sull'emulatore, segui questi passaggi:

  1. In Android Studio, seleziona Esegui > Esegui app o fai clic su EseguiIcona Esegui app in Android Studio nella barra degli strumenti.
  2. Nella finestra di dialogo Seleziona la destinazione del deployment, seleziona un dispositivo e fai clic su OK. La versione del sistema operativo consigliata è Android 10 (livello API 30) o versioni successive, anche se le Azioni app funzionano sui dispositivi fino ad Android 5 (livello API 21).
  3. Premi a lungo il pulsante Home per configurare l'assistente e verificare che funzioni. Dovrai accedere all'assistente sul tuo dispositivo, se non l'hai ancora fatto.

Per ulteriori informazioni sui dispositivi virtuali Android, vedi Creare e gestire i dispositivi virtuali.

Esplora brevemente l'app per vedere cosa sa fare. Se tocchi l'icona Più, viene creata una nuova voce di attività. Le voci di menu in alto a destra ti consentono di cercare e filtrare le voci delle attività in base allo stato di completamento.

4. Crea una classe di repository di scorciatoie

Diverse classi nella nostra app di esempio chiameranno l'API ShortcutManagerCompat per eseguire il push e gestire le scorciatoie dinamiche. Per ridurre la ridondanza del codice, implementerai un repository per consentire alle tue classi di progetto di gestire facilmente le scorciatoie dinamiche.

Il pattern di progettazione del repository fornisce un'API chiara per la gestione delle scorciatoie. Il vantaggio di un repository è che i dettagli dell'API sottostante vengono astratti in modo uniforme dietro un'API minima. Implementa il repository seguendo questi passaggi:

  1. Crea una classe ShortcutsRepository per astrarre l'API ShortcutManagerCompat.
  2. Aggiungi i metodi ShortcutsRepository al Service Locator dell'app.
  3. Registra il servizio ShortcutRepository nell'applicazione principale.

crea il repository

Crea una nuova classe Kotlin denominata ShortcutsRepository nel pacchetto com.example.android.architecture.blueprints.todoapp.data.source. Puoi trovare questo pacchetto organizzato nella cartella app/src/main/java. Utilizzerai questa classe per implementare un'interfaccia che fornisce un insieme minimo di metodi che coprono il nostro caso d'uso del codelab.

Finestra di Android Studio che mostra la posizione della classe ShortcutsRepository.

Figura 2. Finestra File del progetto di Android Studio che mostra la posizione della classe ShortcutsRepository.

Incolla il seguente codice nel nuovo corso:

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>) {
       //...
   }
}

Aggiorna il metodo pushShortcut per chiamare l'API ShortcutManagerCompat. Aggiorna la classe ShortcutsRepository con il seguente codice:

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))
}

Nell'esempio di codice precedente abbiamo passato appContext all'API. Si tratta di una proprietà di classe che contiene un contesto dell'applicazione. È importante utilizzare un contesto dell'applicazione (anziché un contesto dell'attività) per evitare perdite di memoria, poiché il contesto potrebbe essere mantenuto più a lungo del ciclo di vita dell'attività host.

Inoltre, l'API richiede che passiamo un oggetto ShortcutInfoCompat per l'oggetto Tasks. Nel codice di esempio precedente lo facciamo chiamando il metodo privato createShortcutCompat, che aggiorneremo per creare e restituire un oggetto ShortcutInfoCompat. Per farlo, aggiorna lo stub createShortcutCompat con il seguente codice:

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()
}

Gli stub di funzione rimanenti in questa classe si occupano dell'aggiornamento e dell'eliminazione delle scorciatoie dinamiche. Attiva queste funzioni aggiornandole con il seguente codice:

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 })
}

Aggiungi classe a Localizzatore servizio

Dopo aver creato la classe ShortcutsRepository, il passaggio successivo consiste nel rendere disponibili gli oggetti di questa classe al resto dell'app. Questa app gestisce le dipendenze delle classi implementando il pattern service locator. Apri la classe ServiceLocator utilizzando il browser di classi in Android Studio andando a Naviga > Classe e digitando "ServiceLocator". Fai clic sul file Kotlin risultante per aprirlo nel tuo IDE.

Nella parte superiore di ServiceLocator.kt, incolla il seguente codice per importare i pacchetti ShortcutsRepository e 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

Aggiungi i membri e i metodi del servizio ShortcutRepository incollando il codice seguente nel corpo di 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)
       }
   }
 }

Registra il servizio scorciatoia

Il passaggio finale consiste nel registrare il nuovo servizio ShortcutsRepository nell'applicazione. In Android Studio, apri TodoApplication.kt e copia il seguente codice nella parte superiore del file:

TodoApplication.kt

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

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

Aggiungi il seguente codice al corpo della classe per registrare il servizio:

TodoApplication.kt

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

   //...

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

   //...
}

Crea l'app e assicurati che continui a essere eseguita.

5. Esegui il push di una nuova scorciatoia

Una volta creato il servizio di scorciatoie, puoi iniziare a inviare le scorciatoie. Poiché gli utenti generano contenuti (elementi di attività) in questa app e si aspettano di potervi accedere in un secondo momento, attiveremo l'accesso vocale a questi contenuti inviando una scorciatoia dinamica associata all'intent integrato GET_THING ogni volta che un utente crea una nuova attività. In questo modo, l'assistente può indirizzare gli utenti direttamente all'elemento dell'attività richiesto quando attivano la BII chiedendo, ad esempio, "Hey Google, apri la mia lista della spesa su SampleApp".

Abiliti questa funzionalità nell'app di esempio completando questi passaggi:

  1. Importazione del servizio ShortcutsRepository nella classe AddEditTaskViewModel, responsabile della gestione degli oggetti dell'elenco di attività.
  2. Invio di una scorciatoia dinamica quando l'utente crea una nuova attività.

Importa ShortcutsRepository

Dobbiamo prima rendere disponibile il servizio ShortcutsRepository per AddEditTaskViewModel. A questo scopo, importa il servizio in ViewModelFactory, la classe di fabbrica utilizzata dall'app per creare un'istanza degli oggetti ViewModel, tra cui AddEditTaskViewModel.

Apri il browser del corso in Android Studio: Naviga > Class e digitando "ViewModelFA". Fai clic sul file Kotlin risultante per aprirlo nell'IDE.

Incolla il codice seguente nella parte superiore di ViewModelFactory.kt per importare i pacchetti ShortcutsRepository e SuppressLint:

ViewModelFactory.kt

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

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

Poi, sostituisci il corpo di ViewModelFactory con il seguente codice:

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
}

Termina le modifiche ViewModelFactory salendo di un livello e passa ShortcutsRepository al costruttore della fabbrica. Apri il browser dei file di Android Studio andando a Naviga > File e digitando "FragmentExt.kt". Fai clic sul file Kotlin risultante nel pacchetto util per aprirlo nel tuo IDE.

Sostituisci il corpo di FragmentExt.kt con il seguente codice:

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

Esegui il push di una scorciatoia

Con la classe di astrazione ShortcutsRepository disponibile per le classi ViewModel dell'app di esempio, aggiorni AddEditTaskViewModel, la classe ViewModel responsabile della creazione delle note, in modo da eseguire il push di una scorciatoia dinamica ogni volta che un utente crea una nuova nota.

In Android Studio, apri il browser delle classi e digita "AddEditTaskViewModel". Fai clic sul file Kotlin risultante per aprirlo nel tuo IDE.

Innanzitutto, aggiungi il pacchetto ShortcutsRepository a questo corso con la seguente istruzione di importazione:

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

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

Aggiungi quindi la proprietà della classe shortcutsRepository aggiornando il costruttore della classe con il seguente codice:

AddEditTaskViewModel.kt

//...

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

    //...

Con la classe ShortcutsRepository aggiunta, crea una nuova funzione, pushShortcut(), per chiamare questa classe. Incolla la seguente funzione privata nel corpo di AddEditTaskViewModel:

AddEditTaskViewModel.kt

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

Infine, esegui il push di una nuova scorciatoia dinamica ogni volta che viene creata un'attività. Sostituisci i contenuti della funzione saveTask() con il seguente codice:

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)
    }
}

Prova il codice

Siamo finalmente pronti a testare il nostro codice! In questo passaggio, invii una scorciatoia dinamica con attivazione vocale e la ispezioni utilizzando l'app Assistente Google.

Creare un'anteprima

La creazione di un'anteprima utilizzando il plug-in dell'Assistente Google consente la visualizzazione delle scorciatoie dinamiche nell'assistente sul dispositivo di test.

Installa il plug-in di test

Se non hai già il plug-in dell'Assistente Google, installalo seguendo questi passaggi in Android Studio:

  1. Vai a **File > Impostazioni (Android Studio > Preferenze su macOS).
  2. Nella sezione Plugin, vai a Marketplace e cerca "Assistente Google".
  3. Installa lo strumento e riavvia Android Studio.

Creare l'anteprima

Per creare un'anteprima in Android Studio, procedi nel seguente modo:

  1. Fai clic su Strumenti > Assistente Google > "Strumento di test delle Azioni app".
  2. Nella casella Nome app, definisci un nome come "Elenco di cose da fare".
  3. Fai clic su Crea anteprima. Se richiesto, leggi e accetta le norme e i Termini di servizio di Azioni app.

Riquadro di creazione dell&#39;anteprima dello strumento App Actions Test Tool.

Figura 3. Riquadro di creazione dell'anteprima dello strumento App Actions Test Tool.

Durante il test, le scorciatoie dinamiche che invii all'assistente verranno visualizzate nell'assistente organizzate in base al nome dell'app fornito per l'anteprima.

Esegui il push e ispeziona una scorciatoia

Riavvia l'app di esempio sul dispositivo di test ed esegui queste operazioni :

  1. Crea una nuova attività con il titolo "Avvia il codelab"
  2. Apri l'app Assistente Google e di' o digita "Le mie scorciatoie".
  3. Tocca la scheda Esplora. Dovresti visualizzare la scorciatoia di esempio.
  4. Tocca la scorciatoia per richiamarla. L'avvio dell'app dovrebbe essere visualizzato con il nome della scorciatoia precompilato nella casella dei filtri, in modo da poter trovare facilmente l'elemento dell'attività richiesto.

6. (Facoltativo) Aggiornare ed eliminare una scorciatoia

Oltre a inviare nuove scorciatoie dinamiche in fase di runtime, la tua app può aggiornarle per riflettere lo stato corrente dei contenuti e delle preferenze dell'utente. È buona norma aggiornare le scorciatoie esistenti ogni volta che un utente modifica l'elemento di destinazione, ad esempio rinominando un'attività nella nostra app di esempio. Inoltre, devi eliminare una scorciatoia corrispondente ogni volta che la risorsa di destinazione viene rimossa per evitare di mostrare scorciatoie non funzionanti all'utente.

Aggiornare una scorciatoia

Modifica AddEditTaskViewModel per aggiornare una scorciatoia dinamica ogni volta che un utente modifica i dettagli di un elemento dell'attività. Per prima cosa, aggiorna il corpo della classe con il codice seguente per aggiungere una funzione di aggiornamento che utilizzi la nostra classe di repository:

AddEditTaskViewModel.kt

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

A questo punto, modifica la funzione saveTask() in modo da chiamare il nuovo metodo ogni volta che viene aggiornata un'attività esistente.

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)
   }
}

Testa il codice riavviare l'app e seguire questi passaggi:

  1. Rinomina il titolo dell'elemento dell'attività esistente in "Completa il codelab".
  2. Apri l'Assistente Google dicendo "Hey Google, le mie scorciatoie".
  3. Tocca la scheda Esplora. Dovresti vedere un'etichetta breve aggiornata per la scorciatoia di prova.

Rimuovere una scorciatoia

Le scorciatoie delle nostre app di esempio devono essere rimosse ogni volta che un utente elimina un'attività. Nell'app di esempio, la logica di eliminazione delle attività si trova nella classe TaskDetailViewModel. Prima di aggiornare questo corso, dobbiamo aggiornare di nuovo ViewModelFactory per trasferire shortcutsRepository a TaskDetailViewModel.

Apri ViewModelFactory e sostituisci i contenuti del relativo metodo costruttore con il seguente codice:

//...
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
}

Poi apri TaskDetailViewModel. Importa il modulo ShortcutsRepository e dichiara una variabile di istanza utilizzando il seguente codice:

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() {
...
}

Infine, modifica la funzione deleteTask() per chiamare shortcutsRepository in modo da rimuovere una scorciatoia basata sul suo ID ogni volta che viene eliminata un'attività con un taskId corrispondente:

TaskDetailViewModel.kt

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

Per testare il codice, riavvia l'app e segui questi passaggi:

  1. Elimina l'attività di test.
  2. Rinomina il titolo dell'elemento dell'attività esistente in "Completa il codelab".
  3. Apri l'Assistente Google dicendo "Hey Google, le mie scorciatoie".
  4. Tocca la scheda Esplora. Verifica che la scorciatoia di prova non venga più visualizzata.

7. Passaggi successivi

Complimenti! Grazie a te, gli utenti della nostra app di esempio possono tornare facilmente alle note che creano chiedendo all'assistente, ad esempio, "Hey Google, apri la mia lista della spesa su ExampleApp". Le scorciatoie favoriscono un maggiore coinvolgimento degli utenti consentendo loro di riprodurre facilmente le azioni utilizzate di frequente nella tua app.

Argomenti trattati

In questo codelab hai imparato a:

  • Identificare i casi d'uso per il push delle scorciatoie dinamiche in un'app.
  • Riduci la complessità del codice utilizzando repository, inserimento di dipendenze e pattern di progettazione di Service locator.
  • Trasferisci le scorciatoie dinamiche che supportano i comandi vocali ai contenuti delle app generati dagli utenti.
  • Aggiornare e rimuovere le scorciatoie esistenti.

Passaggi successivi

Da qui, puoi provare ad apportare ulteriori perfezionamenti all'app Elenco attività. Per fare riferimento al progetto finito, consulta il ramo del repository –codelab-complete su GitHub.

Ecco alcuni suggerimenti per ulteriori informazioni su come estendere questa app con Azioni app:

Per continuare il tuo percorso con Actions on Google, consulta queste risorse:

Seguici su Twitter @ActionsOnGoogle per non perderti i nostri ultimi annunci e twitta a #appActions per condividere ciò che hai realizzato.

Sondaggio di feedback

Infine, compila questo sondaggio per fornire un feedback sulla tua esperienza con questo codelab.