Rozszerzanie dynamicznych skrótów do Asystenta Google za pomocą działań w aplikacji
Informacje o tym ćwiczeniu (w Codelabs)
1. Omówienie
W poprzednim ćwiczeniu Codelab używaliśmy skrótów statycznych do implementowania w przykładowej aplikacji często używanych wbudowanych intencji. Deweloperzy Androida używają działań aplikacji, aby rozszerzać funkcjonalność 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”.
Rysunek 1. Trzy ekrany pokazujące zadanie utworzone przez użytkownika i Asystenta Google uruchamiającego dynamiczny skrót do tego zadania
Co utworzysz
W tym laboratorium programistycznym włączysz dynamiczne skróty głosowe w przykładowej aplikacji na Androida do tworzenia listy zadań. Dzięki temu użytkownicy będą mogli prosić Asystenta o otwieranie elementów listy zadań utworzonych w aplikacji. Aby to zrobić, użyjesz wzorów architektury Androida, w szczególności wzorów repozytorium, lokalizatora usługi 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 nie masz doświadczenia z aplikowanymi działaniami, przed kontynuowaniem zalecamy ukończenie tego laboratorium kodu.
Zanim przejdziesz dalej, upewnij się, że środowisko programistyczne ma następującą konfigurację:
- terminal do uruchamiania poleceń powłoki z zainstalowanym gitem;
- 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 dostępu głosowego, wykonaj te czynności:
- Powiązanie dynamicznego skrótu z odpowiednim kluczem BII.
- Włączanie Asystenta do 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 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żliwiać 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 ExampleApp” - Skrót powiązany z
START_EXERCISE
BII pozwala użytkownikom wyświetlać sesje ćwiczeń. * „OK Google, poproś ExampleApp o rozpoczęcie zwykłego ćwiczenia”
Pełną listę kategorii BIIs znajdziesz w dokumentacji dotyczącej wbudowanych intencji.
Udostępniam skróty do Asystenta
Po powiązaniu skrótów z interfejsem BII należy umożliwić Asystentowi przetwarzanie tych skrótów. W tym celu dodaj do projektu bibliotekę integracji skrótów Google. Dzięki tej bibliotece Asystent będzie wiedzieć o każdym skrótach przesłanym przez Twoją aplikację, co umożliwi użytkownikom uruchamianie tych skrótów za pomocą odpowiedniego słowa-klucza w Asystencie.
3. Przygotowanie środowiska programistycznego
W tym ćwiczeniu używamy przykładowej aplikacji do listy zadań utworzonej 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ć przykładowe repozytorium GitHub, 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 Welcome to Android Studio (Witamy w Android Studio) kliknij Import project (Importuj projekt).
- Wybierz folder, do którego 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
.
Dodawanie 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 dalsze zmiany w aplikacji, warto zapoznać się z jej możliwościami. Aby uruchomić aplikację na emulatorze, wykonaj te czynności:
- W Android Studio wybierz Uruchom > Uruchom aplikację lub kliknij Uruchom
na pasku narzędzi.
- 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ą już na urządzeniach z Androidem 5 (poziom interfejsu 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 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
, aby przesyłać dynamiczne skróty i nimi zarządzać. Aby ograniczyć nadmiarowość kodu, wdrożysz repozytorium, które umożliwi klasom projektu łatwe zarządzanie dynamicznymi skrótami.
Wzór 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. Aby wdrożyć repozytorium, wykonaj te czynności:
- Utwórz klasę
ShortcutsRepository
, aby zastąpić abstrakcyjnie interfejs APIShortcutManagerCompat
. - Dodaj metody
ShortcutsRepository
do lokalizatora usług aplikacji. - 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.
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 wartość appContext
. To jest właściwość klasy zawierająca kontekst aplikacji. Aby uniknąć wycieków pamięci, używaj kontekstu aplikacji (a nie kontekstu aktywności), ponieważ kontekst może być przechowywany dłużej niż czas trwania aktywności hosta.
Dodatkowo interfejs API wymaga, aby obiekt Task był przekazywany jako obiekt ShortcutInfoCompat
. W poprzednim przykładzie kodu robimy to, wywołując prywatną metodę createShortcutCompat
, którą zaktualizujemy, aby tworzyć i zwracać 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 szablony funkcji w tej klasie dotyczą aktualizowania i usuwania dynamicznych skrótów. 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 })
}
Dodawanie klasy do lokalizatora usług
Po utworzeniu klasy ShortcutsRepository
kolejnym krokiem jest udostępnienie obiektów tej klasy w innych częściach aplikacji. Aplikacja zarządza zależnościami klasy, wdrażając wzór lokalizatora usługi. Otwórz klasę lokalizatora usługi za pomocą przeglądarki klas w Android Studio. W tym celu kliknij Nawiguj > Klasa i wpisz „ServiceLocator”. Kliknij utworzony plik Kotlin, aby otworzyć go w 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 do treści klasy ten kod:
TodoApplication.kt
//...
class TodoApplication : Application() {
//...
val shortcutsRepository: ShortcutsRepository
get() = ServiceLocator.provideShortcutsRepository(this)
//...
}
Skompiluj aplikację i upewnij się, że działa ona prawidłowo.
5. Przekaż nowy skrót
Po utworzeniu usługi skrótów możesz zacząć używać skrótów. Użytkownicy generują w tej aplikacji treści (elementy zadania) i spodziewają się, że będą mogli do nich później wrócić. Dlatego za każdym razem, gdy użytkownik utworzy nowe zadanie, będziemy włączać dostęp do tych treści za pomocą dynamicznego skrótu powiązanego z GET_THING
BII. Dzięki temu Asystent może przekierowywać użytkowników bezpośrednio do żądanego zadania, gdy uruchamiają one BII, prosząc o coś takiego jak „Hej Google, otwórz moją listę zakupów w SampleApp”.
Tę funkcję możesz włączyć w przykładowej aplikacji, wykonując te czynności:
- Importuję usługę
ShortcutsRepository
do klasyAddEditTaskViewModel
. Odpowiada ona za zarządzanie obiektami listy zadań. - Przekazywanie dynamicznego skrótu, gdy użytkownik tworzy nowe zadanie.
Importuj repozytorium skrótów
Najpierw musimy udostępnić usługę ShortcutsRepository
użytkownikom usługi 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
}
Zakończ wprowadzanie zmian w ViewModelFactory
, przechodząc o jeden poziom wyżej i przekazując ShortcutsRepository
konstruktorowi 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
za pomocą tego polecenia 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 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ę prywatną funkcję w ciele funkcji AddEditTaskViewModel
:
AddEditTaskViewModel.kt
//...
private fun pushShortcut(newTask: Task) = viewModelScope.launch {
shortcutsRepository.pushShortcut(newTask)
}
Na koniec wysyłaj nowy dynamiczny skrót za każdym razem, gdy zostanie utworzone zadanie. 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ą w Android Studio, wykonując te czynności:
- Wybierz **Plik > Ustawienia (w systemie macOS Android Studio > Ustawienia).
- W sekcji Wtyczki kliknij Marketplace i wyszukaj „Asystent Google”.
- Jeśli nie możesz znaleźć wtyczki w Marketplace, pobierz ją ręcznie i wykonaj instrukcje opisane w artykule Instalowanie wtyczki z dysku.
- Zainstaluj narzędzie i ponownie uruchom Android 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ń aplikacji”.
- W polu Nazwa aplikacji wpisz nazwę, na przykład „Lista zadań”.
- Kliknij Utwórz podgląd. Gdy pojawi się prośba, przeczytaj i zaakceptuj zasady i warunki korzystania z akcji w aplikacji.
Rysunek 3. Panel tworzenia podglądu w narzędziu Testowanie działań w aplikacji.
Podczas testowania dynamiczne skróty wysyłane do Asystenta będą w nim widoczne, uporządkowane według nazwy aplikacji, którą podano w ramach podglądu.
Przesyłanie i sprawdzanie skrótu
Uruchom ponownie przykładową aplikację na urządzeniu testowym i wykonaj te czynności :
- Utwórz nowe zadanie o nazwie „Rozpocznij ćwiczenia z programowania”
- 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 uruchomić. Po uruchomieniu aplikacji w polu filtra powinna pojawić się nazwa skrótu, co ułatwi znalezienie żądanego elementu zadania.
6. (Opcjonalnie) Aktualizowanie i usuwanie skrótu
Aplikacja może nie tylko wysyłać nowe dynamiczne skróty w czasie działania, ale też aktualizować je, aby odzwierciedlały aktualny stan treści i ustawień użytkownika. Dobrą praktyką jest aktualizowanie istniejących skrótów, gdy użytkownik zmodyfikuje element docelowy, np. zmieni nazwę zadania w naszej przykładowej aplikacji. Należy też usunąć odpowiedni skrót, gdy usuniesz zasób docelowy, aby uniknąć wyświetlania niedziałających skrótów użytkownikowi.
Aktualizowanie skrótu
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)
}
}
Aby przetestować kod, uruchom ponownie aplikację i wykonaj te czynności:
- Zmień nazwę istniejącego elementu zadania na „Zakończ ćwiczenia w programowaniu”.
- Aby otworzyć Asystenta Google, powiedz „OK Google, moje skróty”.
- Kliknij kartę Odkrywaj. Powinieneś zobaczyć zaktualizowaną krótką etykietę testowego skrótu.
Usuwanie skrótu
Nasze przykładowe skróty do aplikacji powinny być usuwane, gdy użytkownik usunie 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:
- usunąć zadanie testowe.
- Zmień nazwę istniejącego elementu zadania na „Zakończ ćwiczenia w programowaniu”.
- Aby otworzyć Asystenta Google, powiedz „OK Google, moje skróty”.
- 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 wracać do tworzonych przez siebie notatek, prosząc Asystenta o coś takiego jak „OK Google, otwórz moją listę zakupów w ExampleApp”. 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
Z tego ćwiczenia na temat programowania dowiesz się, jak:
- Określ przypadki użycia przesyłania 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.
- aktualizować i usuwać istniejące skróty.
Co dalej?
Tutaj możesz dokonać dalszych poprawek w aplikacji Lista zadań. Aby zapoznać się z ukończonym projektem, otwórz repozytorium –gałęzi codelab-complete na GitHubie.
Oto kilka sugestii, jak dowiedzieć się więcej o rozszerzaniu tej aplikacji za pomocą akcji w aplikacji:
- Zapoznaj się z przykładową listą zadań w Google Analytics dla Firebase, aby dowiedzieć się, jak śledzić skuteczność działań w aplikacji.
- Aby dowiedzieć się więcej o tym, jak rozszerzyć swoje aplikacje o Asystenta, zapoznaj się z wbudowanymi intencjami akcji aplikacji.
Aby dalej korzystać z Actions on Google, zapoznaj się z tymi materiałami:
- actions.google.com: oficjalna witryna z dokumentacją Actions on Google.
- Przykładowy indeks akcji w aplikacji: przykładowe aplikacje i kod do przeglądania możliwości w ramach tych działań.
- Repozytorium Actions on Google GitHub: przykładowy kod i biblioteki.
- r/GoogleAssistantDev: oficjalna społeczność na Reddit dotycząca programistów pracujących nad Asystentem Google.
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.