1. Przegląd
W poprzednim Codelabs za pomocą skrótów statycznych zaimplementowano w przykładowej aplikacji często używane wbudowane intencje (BII). Programiści na Androida używają działań w aplikacji, aby rozszerzyć funkcje aplikacji na Asystenta Google.
Statyczne skróty są dołączane do aplikacji i można je aktualizować tylko przez wydawanie nowych wersji aplikacji. Włączanie funkcji głosowych dla dynamicznych elementów w aplikacji, takich jak treści użytkowników, odbywa się za pomocą dynamicznych skrótów. Aplikacje wysyłają skróty dynamiczne po wykonaniu przez użytkowników odpowiednich działań, np. utworzeniu nowej notatki w aplikacji do śledzenia zadań. Dzięki działaniom w aplikacji możesz włączyć te skróty dla poleceń głosowych, wiążąc je z BII. Umożliwi to użytkownikom dostęp do treści z poziomu Asystenta za pomocą poleceń takich jak „OK Google, otwórz moją listę zakupów w ExampleApp”.

Rysunek 1. Trzy ekrany progresywne przedstawiające zadanie utworzone przez użytkownika i Asystenta Google uruchamiającego dynamiczny skrót do tego zadania.
Co utworzysz
W tym module nauczysz się włączać dynamiczne skróty głosowe w przykładowej aplikacji na Androida z listą zadań do wykonania. Dzięki temu użytkownicy będą mogli poprosić Asystenta o otwarcie elementów listy zadań utworzonych w aplikacji. Aby to zrobić, użyjesz wzorców architektury Androida, a w szczególności wzorców repository, service locator i ViewModel.
Wymagania wstępne
Ten samouczek opiera się na koncepcjach działań w aplikacji omówionych w poprzednim samouczku, zwłaszcza na wbudowanych intencjach i statycznych skrótach. Jeśli nie masz doświadczenia w korzystaniu z akcji w aplikacji, przed przejściem dalej zalecamy ukończenie tego laboratorium programowania.
Zanim przejdziesz dalej, upewnij się, że Twoje środowisko programistyczne ma taką konfigurację:
- terminal do uruchamiania poleceń powłoki z zainstalowanym narzędziem Git;
- Najnowsza stabilna wersja Android Studio.
- fizyczne lub wirtualne urządzenie z Androidem z dostępem do internetu;
- konto Google zalogowane w Android Studio, aplikacji Google i aplikacji Asystent Google;
2. Jak to działa
Aby włączyć dynamiczny skrót do dostępu głosowego, wykonaj te czynności:
- Powiązanie skrótu dynamicznego z odpowiednim wbudowanym zamiarem.
- Umożliwienie Asystentowi korzystania ze skrótów przez dodanie biblioteki integracji skrótów Google.
- Wysyłanie skrótu za każdym razem, gdy użytkownik wykona odpowiednie zadanie w aplikacji.
Przypisywanie skrótów
Aby skrót dynamiczny był dostępny z poziomu Asystenta, musi być powiązany z odpowiednim BII. Gdy wywoływany jest wbudowany zamiar z 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
GET_THINGBII może umożliwiać użytkownikom żądanie określonych treści w aplikacji bezpośrednio z Asystenta. * „OK Google, otwórz moją listę zakupów w aplikacji ExampleApp”. - Skrót powiązany z
START_EXERCISEBII może umożliwiać użytkownikom wyświetlanie sesji ćwiczeń. * „OK Google, poproś ExampleApp o rozpoczęcie mojego zwykłego treningu”.
Pełną listę wbudowanych intencji znajdziesz w dokumentacji wbudowanych intencji.
Udostępnianie skrótów Asystentowi
Po powiązaniu skrótów z BII następnym krokiem jest umożliwienie Asystentowi korzystania z tych skrótów przez dodanie do projektu biblioteki integracji skrótów Google. Dzięki tej bibliotece Asystent będzie znać każdy skrót przesłany przez Twoją aplikację, co umożliwi użytkownikom uruchamianie tych skrótów za pomocą frazy wywołującej w Asystencie.
3. Przygotowywanie środowiska programistycznego
W tym ćwiczeniu w Codelabs używamy przykładowej aplikacji do tworzenia list zadań do wykonania na Androida. Dzięki tej aplikacji użytkownicy mogą dodawać elementy do list, wyszukiwać elementy listy zadań według kategorii i filtrować zadania według stanu ukończenia. Pobierz i przygotuj przykładową aplikację, wykonując czynności opisane w tej sekcji.
Pobieranie plików podstawowych
Aby skopiować repozytorium GitHub przykładowej aplikacji, uruchom to polecenie:
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:
- W oknie Witamy w Android Studio kliknij Importuj projekt.
- Wybierz folder, do którego sklonowano repozytorium.
Możesz też wyświetlić wersję przykładowej aplikacji, która reprezentuje ukończone ćwiczenie z programowania, klonując gałąź codelab-complete repozytorium Github:
git clone https://github.com/actions-on-google/app-actions-dynamic-shortcuts.git --branch codelab-complete
Aktualizowanie identyfikatora aplikacji na Androida
Aktualizacja identyfikatora aplikacji jednoznacznie identyfikuje aplikację na urządzeniu testowym i zapobiega wystąpieniu błędu „Zduplikowana nazwa pakietu”, jeśli aplikacja zostanie 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 czymś unikalnym.
Dodawanie zależności interfejsu Shortcuts API
Dodaj do pliku zasobu app/build.gradle te biblioteki Jetpack:
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, warto sprawdzić, co potrafi przykładowa aplikacja. Aby uruchomić aplikację na emulatorze, wykonaj te czynności:
- W Android Studio wybierz Uruchom > Uruchom aplikację lub na pasku narzędzi kliknij Uruchom
. - W oknie Select Deployment Target (Wybierz miejsce docelowe wdrożenia) wybierz urządzenie i kliknij OK. Zalecana wersja systemu operacyjnego to Android 10 (poziom API 30) lub nowszy, chociaż akcje w aplikacji działają na urządzeniach z Androidem 5 (poziom API 21).
- Przytrzymaj przycisk ekranu głównego, aby skonfigurować Asystenta i sprawdzić, czy działa. Jeśli jeszcze tego nie zrobisz, musisz zalogować się w Asystencie na urządzeniu.
Więcej informacji o wirtualnych urządzeniach z Androidem znajdziesz w artykule Tworzenie wirtualnych urządzeń i zarządzanie nimi.
Przejrzyj aplikację, aby zobaczyć, co potrafi. Kliknięcie ikony plusa powoduje utworzenie nowego elementu zadania, a elementy menu w prawym górnym rogu umożliwiają wyszukiwanie i filtrowanie elementów zadań według stanu ukończenia.
4. Tworzenie klasy repozytorium skrótów
Kilka klas w naszej przykładowej aplikacji będzie wywoływać interfejs ShortcutManagerCompat API, aby przesyłać dynamiczne skróty i nimi zarządzać. Aby zmniejszyć nadmiarowość kodu, zaimplementujesz repozytorium, które umożliwi klasom projektu łatwe zarządzanie dynamicznymi skrótami.
Wzorzec repozytorium zapewnia przejrzysty interfejs API do zarządzania skrótami. Zaletą repozytorium jest to, że szczegóły bazowego interfejsu API są jednolicie abstrahowane za pomocą minimalnego interfejsu API. Aby wdrożyć repozytorium, wykonaj te czynności:
- Utwórz klasę
ShortcutsRepository, aby wyodrębnić interfejs APIShortcutManagerCompat. - Dodaj metody
ShortcutsRepositorydo lokalizatora usług aplikacji. - Zarejestruj usługę
ShortcutRepositoryw głównej aplikacji.
Tworzenie repozytorium
Utwórz nową klasę Kotlin o nazwie ShortcutsRepository w pakiecie com.example.android.architecture.blueprints.todoapp.data.source. Ten pakiet znajdziesz w folderze app/src/main/java. Użyjesz tej klasy do zaimplementowania interfejsu udostępniającego minimalny zestaw metod obejmujących nasz przypadek użycia w ćwiczeniu w Codelabs.

Rysunek 2. Okno plików projektu Android Studio z wyświetloną lokalizacją klasy ShortcutsRepository.
Wklej do nowej klasy ten kod:
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 zmodyfikuj metodę pushShortcut, aby wywoływała interfejs ShortcutManagerCompat API. Zaktualizuj klasę ShortcutsRepository tym kodem:
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 przykładowym kodzie powyżej przekazaliśmy do interfejsu API wartość appContext. Jest to właściwość klasy zawierająca kontekst aplikacji. Aby uniknąć wycieków pamięci, ważne jest, aby używać kontekstu aplikacji (w przeciwieństwie do 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 powyższym przykładzie kodu osiągamy to, wywołując metodę prywatną createShortcutCompat, którą zaktualizujemy, aby utworzyć i zwrócić obiekt ShortcutInfoCompat. Aby to zrobić, zaktualizuj element 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 stuby funkcji w tej klasie dotyczą aktualizowania i usuwania skrótów dynamicznych. Włącz te funkcje, aktualizując je za pomocą tego kodu:
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 })
}
Dodawanie klasy do lokalizatora usługi
Po utworzeniu klasy ShortcutsRepository następnym krokiem jest udostępnienie utworzonych obiektów tej klasy reszcie aplikacji. Aplikacja zarządza zależnościami klas, wdrażając wzorzec lokalizatora usług. Otwórz klasę lokalizatora usług za pomocą przeglądarki klas w Android Studio. W tym celu kliknij Nawigacja > Klasa i wpisz „ServiceLocator”. Kliknij utworzony plik Kotlin, aby otworzyć go w IDE.
U góry pliku 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 elementy usługi ShortcutRepository i metody, wklejając ten kod do treści pliku 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)
}
}
}
Zarejestruj usługę skrótu
Ostatnim krokiem jest zarejestrowanie nowej usługi ShortcutsRepository w aplikacji. W Android Studio otwórz plik TodoApplication.kt i skopiuj ten kod w górnej części 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)
//...
}
Skompiluj aplikację i upewnij się, że nadal działa.
5. Wypchnij nowy skrót
Po utworzeniu usługi skrótów możesz zacząć przesyłać skróty. Użytkownicy generują w tej aplikacji treści (elementy zadań) i oczekują, że będą mogli do nich później wrócić. Dlatego umożliwimy dostęp do tych treści za pomocą głosu, przesyłając dynamiczny skrót powiązany z BII GET_THING za każdym razem, gdy użytkownik utworzy nowe zadanie. Dzięki temu Asystent może bezpośrednio uruchamiać żądany element zadania, gdy użytkownik wywoła BII, zadając pytania typu „OK Google, otwórz moją listę zakupów w aplikacji SampleApp”.
Aby włączyć tę funkcję w przykładowej aplikacji, wykonaj te czynności:
- Importowanie usługi
ShortcutsRepositorydo klasyAddEditTaskViewModel, która odpowiada za zarządzanie obiektami listy zadań. - Wysyłanie skrótu dynamicznego, gdy użytkownik tworzy nowe zadanie.
Importowanie repozytorium skrótów
Najpierw musimy udostępnić usługę ShortcutsRepository w AddEditTaskViewModel. Aby to zrobić, zaimportuj usługę do ViewModelFactory, czyli klasy fabrycznej, której aplikacja używa do tworzenia instancji obiektów ViewModel, w tym AddEditTaskViewModel.
Otwórz przeglądarkę klas w Android Studio, klikając Nawigacja > Klasa i wpisując „ViewModelFactory”. Kliknij utworzony plik Kotlin, aby otworzyć go w IDE.
U góry pliku 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ść pliku 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
}
Zakończ ViewModelFactory zmiany, przechodząc o jeden poziom wyżej, i przekaż ShortcutsRepository do konstruktora fabryki. Otwórz przeglądarkę plików Android Studio, klikając Nawigacja > Plik i wpisując „FragmentExt.kt”. Kliknij powstały plik Kotlin w pakiecie util, aby otworzyć go w IDE.
Zastąp treść pliku 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)
}
Wysyłanie skrótu
Dzięki klasie abstrakcji ShortcutsRepository dostępnej dla klas ViewModel aplikacji przykładowej możesz zaktualizować klasę AddEditTaskViewModel, czyli klasę ViewModel odpowiedzialną za tworzenie notatek, aby za każdym razem, gdy użytkownik utworzy nową notatkę, wysyłać dynamiczny skrót.
W Android Studio otwórz przeglądarkę klas i wpisz „AddEditTaskViewModel”. Kliknij utworzony plik Kotlin, aby otworzyć go w IDE.
Najpierw dodaj do tej klasy pakiet ShortcutsRepository za pomocą tej 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 klasy tym kodem:
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 pliku AddEditTaskViewModel:
AddEditTaskViewModel.kt
//...
private fun pushShortcut(newTask: Task) = viewModelScope.launch {
shortcutsRepository.pushShortcut(newTask)
}
Na koniec za każdym razem, gdy utworzysz zadanie, wyślij nowy skrót dynamiczny. 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 wypchniesz dynamiczny skrót z obsługą głosową i sprawdzisz go za pomocą aplikacji Asystent Google.
Tworzenie wersji przedpremierowej
Utworzenie podglądu za pomocą wtyczki Asystenta Google umożliwia wyświetlanie skrótów dynamicznych w Asystencie na urządzeniu testowym.
Instalowanie wtyczki testowej
Jeśli nie masz jeszcze wtyczki Asystenta Google, zainstaluj ją, wykonując te czynności w Android Studio:
- Kliknij **Plik > Ustawienia (Android Studio > Preferencje na macOS).
- W sekcji Wtyczki otwórz Marketplace i wyszukaj „Asystent Google”.
- Jeśli nie możesz znaleźć wtyczki w Marketplace, pobierz ją ręcznie i postępuj zgodnie z instrukcjami w artykule Instalowanie wtyczki z dysku.
- Zainstaluj narzędzie i ponownie uruchom Androida Studio.
Tworzenie podglądu
Aby utworzyć podgląd, wykonaj te czynności w Android Studio:
- Kliknij Narzędzia > Asystent Google > „Narzędzie do testowania działań w aplikacji”.
- W polu Nazwa aplikacji wpisz nazwę, np. „Lista zadań”.
- Kliknij Utwórz podgląd. Jeśli pojawi się taka prośba, zapoznaj się z zasadami dotyczącymi akcji w aplikacji i warunkami korzystania z usługi i je zaakceptuj.

Rysunek 3. Panel podglądu tworzenia w narzędziu do testowania akcji w aplikacji.
Podczas testowania dynamiczne skróty, które przesyłasz do Asystenta, będą wyświetlane w Asystencie w kolejności określonej przez nazwę aplikacji podaną w podglądzie.
Przesyłanie i sprawdzanie skrótu
Uruchom ponownie aplikację przykładową na urządzeniu testowym i wykonaj te czynności :
- Utwórz nowe zadanie o nazwie „Start codelab”.
- Otwórz aplikację Asystent Google i powiedz lub wpisz „Moje skróty”.
- Kliknij kartę Odkrywaj. Powinien być widoczny przykładowy skrót.
- Kliknij skrót, aby go wywołać. Aplikacja powinna się uruchomić z nazwą skrótu wstępnie wypełnioną w polu filtra, co ułatwi znalezienie żądanego elementu zadania.
6. (Opcjonalnie) Aktualizowanie i usuwanie skrótu
Oprócz wysyłania nowych skrótów dynamicznych w czasie działania aplikacja może je aktualizować, aby odzwierciedlały bieżący stan treści i preferencji użytkownika. Dobrym rozwiązaniem jest aktualizowanie istniejących skrótów za każdym razem, gdy użytkownik zmodyfikuje element docelowy, np. zmieni nazwę zadania w naszej przykładowej aplikacji. Należy też usuwać odpowiedni skrót za każdym razem, gdy zasób docelowy zostanie usunięty, aby uniknąć wyświetlania użytkownikowi uszkodzonych skrótów.
Aktualizowanie skrótu
Modyfikuj AddEditTaskViewModel, aby aktualizować skrót dynamiczny za każdym razem, gdy użytkownik zmieni szczegóły elementu zadania. Najpierw zaktualizuj treść klasy, dodając ten kod, aby dodać funkcję aktualizacji, która korzysta z naszej klasy repozytorium:
AddEditTaskViewModel.kt
private fun updateShortcut(newTask: Task) = viewModelScope.launch {
shortcutsRepository.updateShortcuts(listOf(newTask))
}
Następnie zmodyfikuj funkcję saveTask() tak, aby wywoływała naszą nową metodę za każdym razem, gdy aktualizowane jest istniejące zadanie.
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:
- Zmień nazwę istniejącego zadania na „Ukończ codelab”.
- Otwórz Asystenta Google, mówiąc „OK Google, moje skróty”.
- Kliknij kartę Odkrywaj. Powinna się wyświetlić zaktualizowana krótka etykieta skrótu testowego.
Usuwanie skrótu
Nasze skróty do przykładowych aplikacji powinny być usuwane, gdy użytkownik usunie zadanie. W przykładowej aplikacji logika usuwania zadań znajduje się w klasie TaskDetailViewModel. Zanim zaktualizujemy tę klasę, musimy ponownie zaktualizować ViewModelFactory, aby przekazać shortcutsRepository do TaskDetailViewModel.
Otwórz plik ViewModelFactory i zastąp zawartość 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, używając 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 zmodyfikuj funkcję deleteTask() tak, aby wywoływała funkcję shortcutsRepository w celu usunięcia skrótu na podstawie jego identyfikatora za każdym razem, gdy zostanie usunięte zadanie z odpowiednim parametrem 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:
- Usuń zadanie testowe.
- Zmień nazwę istniejącego zadania na „Ukończ codelab”.
- Otwórz Asystenta Google, mówiąc „OK Google, moje skróty”.
- Kliknij kartę Odkrywaj. Sprawdź, czy skrót testowy już się nie wyświetla.
7. Dalsze kroki
Gratulacje! Dzięki temu użytkownicy naszej przykładowej aplikacji mogą łatwo wracać do utworzonych przez siebie notatek, zadając Asystentowi pytania takie jak „OK Google, otwórz moją listę zakupów w aplikacji ExampleApp”. Skróty zachęcają użytkowników do większego zaangażowania, ponieważ ułatwiają im ponowne odtwarzanie często używanych działań w aplikacji.
Omówione zagadnienia
Z tego modułu dowiedzieliśmy się, jak:
- Określanie przypadków użycia dynamicznych skrótów w aplikacji.
- Zmniejsz złożoność kodu za pomocą wzorców projektowych repozytorium, wstrzykiwania zależności i lokalizatora usług.
- Wysyłaj dynamiczne skróty głosowe do treści aplikacji generowanych przez użytkowników.
- Aktualizowanie i usuwanie dotychczasowych skrótów.
Co dalej
Możesz teraz wprowadzić dalsze ulepszenia w aplikacji Task List. Aby zobaczyć gotowy projekt, zapoznaj się z repozytorium –codelab-complete branch w GitHubie.
Oto kilka sugestii, które pomogą Ci dowiedzieć się więcej o rozszerzaniu tej aplikacji za pomocą akcji w aplikacji:
- Aby dowiedzieć się, jak śledzić skuteczność działań w aplikacji, zapoznaj się z przykładową listą zadań z Google Analytics dla Firebase.
- Więcej sposobów na rozszerzenie aplikacji o Asystenta znajdziesz w dokumentacji wbudowanych intencji akcji w aplikacji.
Aby kontynuować przygodę z Actions on Google, zapoznaj się z tymi materiałami:
- actions.google.com oficjalna witryna z dokumentacją dotyczącą Actions on Google.
- Przykładowy indeks akcji w aplikacji: przykładowe aplikacje i kod do poznawania możliwości akcji w aplikacji.
- Repozytorium GitHub Actions on Google: przykładowy kod i biblioteki.
- r/GoogleAssistantDev: oficjalna społeczność Reddit dla programistów pracujących z Asystentem Google.
Obserwuj nas na Twitterze @ActionsOnGoogle, aby być na bieżąco z najnowszymi ogłoszeniami. Możesz też użyć hashtagu #appActions, aby podzielić się tym, co udało Ci się stworzyć.
Ankieta do zbierania opinii
Na koniec wypełnij tę ankietę, aby podzielić się opinią na temat tego samouczka.