Rozszerzaj dynamiczne skróty do Asystenta Google za pomocą działań w aplikacji

1. Omówienie

W poprzednim ćwiczeniu z programowania wykorzystaliśmy statyczne skróty, aby wdrożyć w przykładowej aplikacji często używane intencje wbudowane (BII). Deweloperzy aplikacji na Androida korzystają z akcji w aplikacji, aby rozszerzać funkcje aplikacji o Asystenta Google.

Skróty statyczne są połączone z aplikacją i można je aktualizować tylko po opublikowaniu nowych wersji aplikacji. W przypadku elementów dynamicznych w aplikacji, takich jak treści użytkowników, funkcje głosowe można włączyć za pomocą skrótów dynamicznych. Aplikacje przekazują dynamiczne skróty po wykonaniu przez użytkownika odpowiednich działań, np. utworzeniu nowej notatki w aplikacji do śledzenia zadań. Akcje w aplikacji umożliwiają włączanie poleceń głosowych w tych skrótach. Aby umożliwić użytkownikom dostęp do treści z pomocy Asystenta, wystarczy, że powiesz na przykład „OK Google, otwórz moją listę zakupów w ExampleApp”.

3 ekrany progresywne pokazujące Asystenta Google uruchamiającego dynamiczny skrót.

Rysunek 1. 3 ekrany progresywne z zadaniem utworzonym przez użytkownika oraz z Asystentem Google uruchamiającym dynamiczny skrót do tego elementu.

Co utworzysz

W ramach tego ćwiczenia w programie włączysz dynamiczne skróty głosowe w przykładowej aplikacji na Androida z listą zadań. Dzięki temu użytkownicy będą mogli poprosić Asystenta o otwarcie elementów listy zadań, które utworzyli w aplikacji. Możesz to zrobić, korzystając z wzorców architektury Androida, a w szczególności wzorców repozytorium, lokalizatora usług i ViewModel.

Wymagania wstępne

To ćwiczenie w Codelabs opiera się na pojęciach związanych z działaniami w aplikacji omówionymi w poprzednim ćwiczeniu z programowania, w szczególności o BII i statycznych skrótach. Jeśli dopiero zaczynasz korzystać z akcji w aplikacji, zalecamy najpierw ukończyć ten moduł Codelabs.

Zanim przejdziesz dalej, upewnij się też, że Twoje środowisko programistyczne ma taką konfigurację:

  • Terminal do uruchamiania poleceń powłoki z zainstalowanym git.
  • Najnowsza stabilna wersja Android Studio.
  • Fizyczne lub wirtualne urządzenie z Androidem z dostępem do internetu.
  • konto Google zalogowane w Android Studio oraz w aplikacji Google i Asystent Google.

2. Jak to działa

Aby włączyć dynamiczny skrót dostępu głosowego, wykonaj te czynności:

  • Powiązanie dynamicznego skrótu z odpowiednim kluczem BII.
  • Umożliwienie Asystentowi przetwarzania skrótów przez dodanie biblioteki integracji skrótów Google.
  • Wypchnięcie skrótu za każdym razem, gdy użytkownik wykona odpowiednie zadanie w aplikacji.

Skróty powiązań

Aby skrót dynamiczny był dostępny z poziomu Asystenta, musi być powiązany z odpowiednim blokiem BII. Po wywołaniu funkcji BII ze skrótem Asystent dopasowuje parametry w żądaniu użytkownika do słów kluczowych zdefiniowanych w powiązanym skrócie. Na przykład:

  • Skrót powiązany z blokiem dostępu do GET_THING BII może umożliwić użytkownikom wysyłanie próśb o dostęp do określonych treści w aplikacji bezpośrednio z poziomu Asystenta. * „OK Google, otwórz moją listę zakupów w aplikacji Przykładowa aplikacja”.
  • Skrót powiązany z blokiem BII ORDER_MENU_ITEM umożliwia użytkownikom ponowne odtwarzanie poprzednich zamówień. * „OK Google, zamów moje zwykłe zamówienie w aplikacji Przykładowa aplikacja”

Pełną listę sklasyfikowanych identyfikatorów BII znajdziesz w dokumentacji dotyczącej intencji wbudowanych.

Udostępniam skróty do Asystenta

Po powiązaniu skrótów z BII następnym krokiem jest włączenie Asystenta do przetwarzania tych skrótów przez dodanie do projektu biblioteki integracji skrótów Google. Po utworzeniu tej biblioteki Asystent będzie wiedzieć o każdym skrótach przekazanych przez aplikację, umożliwiając użytkownikom uruchamianie tych skrótów za pomocą wyrażenia aktywującego tego skrótu w Asystencie.

3. Przygotowywanie środowiska programistycznego

W tym ćwiczeniu w Codelabs wykorzystano przykładową aplikację do tworzenia listy zadań na Androida. Ta aplikacja pozwala użytkownikom dodawać elementy do list, wyszukiwać elementy list zadań według kategorii i filtrować zadania według stanu ukończenia. Wypełnij tę sekcję, aby pobrać i przygotować przykładową aplikację.

Pobieranie plików podstawowych

Uruchom to polecenie, aby sklonować repozytorium przykładowej aplikacji na GitHubie:

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

Po sklonowaniu repozytorium wykonaj te czynności, aby otworzyć je w Android Studio:

  1. W oknie Welcome to Android Studio (Witamy w Android Studio) kliknij Import project (Importuj projekt).
  2. Wybierz folder, w którym sklonowano repozytorium.

Możesz też wyświetlić wersję przykładowej aplikacji reprezentującej ukończone ćwiczenia z programowania, sklonując gałąź codelab-complete swojego repozytorium GitHub:

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

Aktualizowanie identyfikatora aplikacji na Androida

Aktualizowanie identyfikatora aplikacji jednoznacznie identyfikuje aplikację na urządzeniu testowym i unika „zduplikowanej nazwy pakietu”. występuje wtedy, gdy aplikacja została przesłana do Konsoli Play. Aby zaktualizować identyfikator aplikacji, otwórz app/build.gradle:

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

Zastąp „MYUNIQUENAME” w polu applicationId.

Dodaj zależności interfejsu Shortcuts API

Dodaj te biblioteki Jetpack do pliku zasobów 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'
   ...
}

Testowanie aplikacji na urządzeniu

Zanim wprowadzisz kolejne zmiany w aplikacji, zapoznaj się z jej możliwościami. Aby uruchomić aplikację w emulatorze, wykonaj te czynności:

  1. W Android Studio wybierz Uruchom > Uruchom aplikację lub kliknij UruchomIkona aplikacji z Androidem Studio na pasku narzędzi.
  2. W oknie Wybierz cel wdrożenia wybierz urządzenie i kliknij OK. Zalecana wersja systemu operacyjnego to Android 10 (poziom interfejsu API 30) lub nowszy, chociaż akcje w aplikacji działają na urządzeniach już od Androida 5 (poziom interfejsu API 21).
  3. Przytrzymaj przycisk ekranu głównego, aby skonfigurować Asystenta i sprawdzić, czy działa. Musisz zalogować się w Asystencie na swoim urządzeniu (chyba że masz to już za sobą).

Więcej informacji o urządzeniach wirtualnych z Androidem znajdziesz w artykule Tworzenie urządzeń wirtualnych i zarządzanie nimi.

Omów krótko aplikację, aby poznać jej możliwości. Kliknięcie ikony plusa powoduje utworzenie nowego zadania. Elementy menu w prawym górnym rogu umożliwiają wyszukiwanie i filtrowanie elementów zadania według stanu ukończenia.

4. Tworzenie klasy repozytorium skrótów

Kilka klas w naszej przykładowej aplikacji będzie wywoływać interfejs API ShortcutManagerCompat w celu przekazywania dynamicznych skrótów i zarządzania nimi. Aby ograniczyć nadmiarowość kodu, wdrożysz repozytorium, które umożliwi klasom projektu łatwe zarządzanie dynamicznymi skrótami.

Wzorzec projektu repozytorium udostępnia przejrzysty interfejs API do zarządzania skrótami. Zaletą repozytorium jest to, że szczegóły bazowego interfejsu API są równomiernie wyodrębniane za pomocą minimalnego interfejsu API. Wdróż repozytorium, wykonując te czynności:

  1. Utwórz klasę ShortcutsRepository, aby wyodrębnić interfejs API ShortcutManagerCompat.
  2. Dodaj metody ShortcutsRepository do lokalizatora usług aplikacji.
  3. Zarejestruj usługę ShortcutRepository w głównej aplikacji.

Tworzenie repozytorium

Utwórz nową klasę Kotlin o nazwie ShortcutsRepository w pakiecie com.example.android.architecture.blueprints.todoapp.data.source. Znajdziesz ten pakiet w folderze app/src/main/java. Wykorzystasz tę klasę do wdrożenia interfejsu zapewniającego minimalny zestaw metod obejmujących nasz przypadek użycia.

Okno Android Studio z lokalizacją klasy ShortcutsRepository

Rysunek 2. Okno Pliki projektu w Android Studio wyświetlające lokalizację klasy ShortcutsRepository.

Wklej ten kod do nowych zajęć:

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

Następnie zaktualizuj metodę pushShortcut tak, aby wywoływała interfejs API ShortcutManagerCompat. Zaktualizuj klasę ShortcutsRepository za pomocą tego kodu:

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

W poprzednim przykładzie kodu przekazaliśmy do interfejsu API appContext. Jest to właściwość klasy przechowująca kontekst aplikacji. Aby uniknąć wycieków pamięci, należy używać kontekstu aplikacji (a nie kontekstu aktywności), ponieważ kontekst może być przechowywany dłużej niż cykl życia aktywności hosta.

Dodatkowo interfejs API wymaga przekazania obiektu ShortcutInfoCompat dla obiektu Task. W poprzednim przykładzie kodu uzyskujemy to przez wywołanie metody prywatnej createShortcutCompat, którą zaktualizujemy, aby utworzyć i zwrócić obiekt ShortcutInfoCompat. W tym celu zaktualizuj fragment kodu createShortcutCompat za pomocą tego kodu:

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

Pozostałe odcinki funkcji w tej klasie dotyczą aktualizowania i usuwania skrótów dynamicznych. Włącz te funkcje, dodając do nich ten kod:

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

Dodaj klasę do lokalizatora usług

Następnym krokiem po utworzeniu klasy ShortcutsRepository jest udostępnienie obiektów tej klasy utworzonych w instancji reszcie aplikacji. Ta aplikacja zarządza zależnościami klas przez wdrożenie wzorca lokalizatora usług. Otwórz klasę lokalizatora usług w przeglądarce zajęć w Android Studio. W tym celu wybierz Nawigacja > Class i wpisz „ServiceLocator”. Kliknij wynikowy plik Kotlin, aby otworzyć go w swoim IDE.

Na górze ServiceLocator.kt wklej ten kod, aby zaimportować pakiety ShortcutsRepository i 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

Dodaj członków usługi i metody ShortcutRepository, wklejając ten kod w treści 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)
       }
   }
 }

Rejestrowanie usługi skrótu

Ostatnim krokiem jest zarejestrowanie nowej usługi ShortcutsRepository w aplikacji. W Android Studio otwórz TodoApplication.kt i skopiuj ten kod u góry pliku:

TodoApplication.kt

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

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

Następnie zarejestruj usługę, dodając ten kod do treści klasy:

TodoApplication.kt

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

   //...

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

   //...
}

Utwórz aplikację i upewnij się, że nadal działa.

5. Przekaż nowy skrót

Po utworzeniu usługi skrótów możesz zacząć używać skrótów. Użytkownicy generują treści (elementy zadań) w tej aplikacji i spodziewają się, że będą mogli do nich wrócić później, dlatego umożliwimy dostęp głosowy do tych treści, naciskając dynamiczny skrót powiązany z GET_THING BII za każdym razem, gdy użytkownik utworzy nowe zadanie. Dzięki temu, gdy aktywują oni BII, Asystent będzie mógł kierować użytkowników bezpośrednio do żądanego elementu zadania, mówiąc na przykład „OK Google, otwórz moją listę zakupów w aplikacji SampleApp”.

Tę funkcję możesz włączyć w przykładowej aplikacji, wykonując te czynności:

  1. Importuję usługę ShortcutsRepository do klasy AddEditTaskViewModel. Odpowiada ona za zarządzanie obiektami listy zadań.
  2. Przekazywanie dynamicznego skrótu, gdy użytkownik tworzy nowe zadanie.

Importuj repozytorium skrótów

Najpierw musimy udostępnić usługę ShortcutsRepository użytkownikowi AddEditTaskViewModel. Aby to zrobić, zaimportuj usługę do ViewModelFactory, klasy fabrycznej, której aplikacja używa do tworzenia instancji obiektów ViewModel, w tym AddEditTaskViewModel.

Otwórz przeglądarkę zajęć w Android Studio. W tym celu kliknij Nawigacja > Class i wpisz „ViewModelFactory”. Kliknij wynikowy plik Kotlin, aby otworzyć go w swoim IDE.

Na górze ViewModelFactory.kt wklej ten kod, aby zaimportować pakiety ShortcutsRepository i SuppressLint:

ViewModelFactory.kt

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

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

Następnie zastąp treść pola ViewModelFactory tym kodem:

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
}

Dokończ zmiany elementu ViewModelFactory, przechodząc o jedną warstwę w górę i przekazując parametr ShortcutsRepository do konstruktora fabryki. Otwórz przeglądarkę plików Android Studio, wybierając Nawigacja > File (Plik) i wpisz „FragmentExt.kt”. Kliknij wynikowy plik Kotlin znajdujący się w pakiecie util, aby otworzyć go w swoim IDE.

Zastąp treść pola FragmentExt.kt tym kodem:

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

Wypchnij skrót

Gdy klasa abstrakcji ShortcutsRepository jest dostępna dla klas przykładowej aplikacji ViewModel, zaktualizujesz AddEditTaskViewModel (klasę ViewModel odpowiedzialną za tworzenie notatek), tak aby przy każdym tworzeniu nowej notatki przez użytkownika wypchnięto dynamiczny skrót.

W Android Studio otwórz przeglądarkę zajęć i wpisz „AddEditTaskViewModel”. Kliknij wynikowy plik Kotlin, aby otworzyć go w swoim IDE.

Najpierw dodaj do tej klasy pakiet ShortcutsRepository przy użyciu następującej instrukcji importu:

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

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

Następnie dodaj właściwość klasy shortcutsRepository, aktualizując konstruktor klas za pomocą tego kodu:

AddEditTaskViewModel.kt

//...

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

    //...

Po dodaniu klasy ShortcutsRepository utwórz nową funkcję pushShortcut(), aby wywołać tę klasę. Wklej tę funkcję prywatną do treści AddEditTaskViewModel:

AddEditTaskViewModel.kt

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

Na koniec wypchnij nowy dynamiczny skrót po utworzeniu zadania. Zastąp zawartość funkcji saveTask() tym kodem:

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

Testowanie kodu

Możemy wreszcie przetestować nasz kod! W tym kroku musisz nacisnąć dynamiczny skrót z obsługą głosu i sprawdzić go za pomocą aplikacji Asystent Google.

Tworzenie wersji przedpremierowej

Utworzenie podglądu przy użyciu wtyczki Asystenta Google umożliwia wyświetlanie dynamicznych skrótów w Asystencie na urządzeniu testowym.

Instalowanie wtyczki testowej

Jeśli nie masz jeszcze wtyczki Asystenta Google, zainstaluj ją, wykonując w Android Studio te czynności:

  1. Wybierz **Plik > Ustawienia (w systemie macOS Android Studio > Ustawienia).
  2. W sekcji Wtyczki otwórz Marketplace i wyszukaj „Asystent Google”.
  3. Zainstaluj narzędzie i uruchom ponownie Android Studio.

Tworzenie podglądu

Aby utworzyć podgląd, wykonaj te czynności w Android Studio:

  1. Kliknij Narzędzia > Asystent Google > „App Actions Test Tool
  2. W polu Nazwa aplikacji wpisz nazwę, na przykład „Lista zadań”.
  3. Kliknij Utwórz podgląd. Gdy pojawi się prośba, przeczytaj i zaakceptuj zasady i warunki korzystania z akcji w aplikacji.

Okienko tworzenia podglądu w narzędziu App Actions Test Tool.

Rysunek 3. Okienko tworzenia podglądu w narzędziu App Actions Test Tool.

Podczas testów dynamiczne skróty przekazane do Asystenta będą widoczne w Asystencie uporządkowane według nazwy aplikacji podanej dla podglądu.

Wypchnij i sprawdź skrót

Uruchom ponownie przykładową aplikację na urządzeniu testowym i wykonaj te czynności :

  1. Utwórz nowe zadanie o nazwie „Rozpocznij ćwiczenia z programowania”
  2. Otwórz aplikację Asystent Google i powiedz lub wpisz „Moje skróty”.
  3. Kliknij kartę Odkrywaj. Powinien być widoczny przykładowy skrót.
  4. Kliknij skrót, aby go wywołać. Powinna pojawić się informacja o uruchomieniu aplikacji z wstępnie wypełnioną nazwą skrótu w polu filtra, co ułatwi znalezienie żądanego elementu zadania.

6. (Opcjonalnie) Aktualizowanie i usuwanie skrótu

Oprócz wprowadzania nowych dynamicznych skrótów w czasie działania aplikacja może je aktualizować, aby odzwierciedlały obecny stan treści i preferencji użytkownika. Zaleca się aktualizowanie istniejących skrótów za każdym razem, gdy użytkownik modyfikuje element docelowy, na przykład zmieniając nazwę zadania w naszej przykładowej aplikacji. Musisz też usunąć odpowiedni skrót po każdym usunięciu zasobu docelowego, aby uniknąć wyświetlania użytkownikowi uszkodzonych skrótów.

Zaktualizuj skrót

Zmodyfikuj AddEditTaskViewModel, aby aktualizować skrót dynamiczny za każdym razem, gdy użytkownik zmieni szczegóły elementu zadania. Najpierw zaktualizuj treść klasy przy użyciu następującego kodu, aby dodać funkcję aktualizacji, która korzysta z klasy repozytorium:

AddEditTaskViewModel.kt

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

Następnie zmień funkcję saveTask(), aby wywoływała naszą nową metodę po każdej aktualizacji istniejącego zadania.

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

Przetestuj kod, ponownie uruchamiając aplikację i wykonując te czynności:

  1. Zmień nazwę istniejącego elementu zadania na „Zakończ ćwiczenia w programowaniu”.
  2. Otwórz Asystenta Google, mówiąc „OK Google, moje skróty”.
  3. Kliknij kartę Odkrywaj. Powinna pojawić się zaktualizowana krótka etykieta skrótu testowego.

Usuwanie skrótu

Nasze skróty do przykładowych aplikacji powinny być usuwane za każdym razem, gdy użytkownik usuwa zadanie. W przykładowej aplikacji logika usuwania zadań znajduje się w klasie TaskDetailViewModel. Zanim zaktualizujemy te zajęcia, musimy ponownie zaktualizować zasadę ViewModelFactory, aby przekazać shortcutsRepository do zajęć TaskDetailViewModel.

Otwórz plik ViewModelFactory i zastąp zawartość jego metody konstruktora tym kodem:

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

Następnie otwórz TaskDetailViewModel. Zaimportuj moduł ShortcutsRepository i zadeklaruj dla niego zmienną instancji za pomocą tego kodu:

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

Na koniec zmień funkcję deleteTask() tak, aby wywoływała funkcję shortcutsRepository, co spowoduje usunięcie skrótu na podstawie jego identyfikatora za każdym razem, gdy zostanie usunięte zadanie z odpowiednim identyfikatorem taskId:

TaskDetailViewModel.kt

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

Aby przetestować kod, uruchom ponownie aplikację i wykonaj te czynności:

  1. Usuń zadanie testowe.
  2. Zmień nazwę istniejącego elementu zadania na „Zakończ ćwiczenia w programowaniu”.
  3. Otwórz Asystenta Google, mówiąc „OK Google, moje skróty”.
  4. Kliknij kartę Odkrywaj. Sprawdź, czy skrót testowy już się nie wyświetla.

7. Dalsze kroki

Gratulacje! Dzięki Tobie użytkownicy naszej przykładowej aplikacji mogą łatwo wrócić do tworzonych przez siebie notatek, prosząc Asystenta na przykład o „OK Google, otwórz moją listę zakupów w aplikacji Przykładowa aplikacja”. Skróty zwiększają zaangażowanie użytkowników, ponieważ ułatwiają im ponowne odtwarzanie często używanych działań w aplikacji.

Omówione zagadnienia

Dzięki temu ćwiczeniu w programie omówiliśmy, jak:

  • Zidentyfikuj przypadki użycia dynamicznych skrótów w aplikacji.
  • Zmniejsz złożoność kodu przy użyciu wzorców projektowych repozytorium, wstrzykiwania zależności i lokalizatora usług.
  • Dodawaj do treści aplikacji użytkowników dynamiczne skróty z obsługą głosu.
  • Aktualizowanie i usuwanie skrótów.

Co dalej?

Tutaj możesz spróbować doprecyzować listę zadań w aplikacji. Aby odwołać się do gotowego projektu, zobacz gałąź –codelab-complete repozytorium na GitHubie.

Oto kilka sugestii, dzięki którym możesz dowiedzieć się więcej o rozszerzaniu możliwości korzystania z tej aplikacji za pomocą działań w aplikacji:

Aby dalej korzystać z Actions on Google, zapoznaj się z tymi materiałami:

Obserwuj nas na Twitterze @ActionsOnGoogle, aby być na bieżąco z najnowszymi informacjami. Aby poinformować o swoich dokonaniach, opublikuj tweeta z hashtagiem #appActions.

Ankieta dotycząca opinii

Na koniec wypełnij tę ankietę, aby przekazać nam swoją opinię na temat tego ćwiczenia z programowania.