Memperluas pintasan dinamis ke Asisten Google dengan Action Aplikasi

1. Ringkasan

Dalam codelab sebelumnya, Anda menggunakan pintasan statis untuk menerapkan intent bawaan (BII) yang biasa digunakan dalam aplikasi contoh. Developer Android menggunakan Action Aplikasi untuk memperluas fungsi aplikasi ke Asisten Google.

Pintasan statis dipaketkan dengan aplikasi dan hanya dapat diperbarui dengan merilis versi baru aplikasi. Mengaktifkan fungsi suara untuk elemen dinamis dalam aplikasi, seperti konten buatan pengguna, dapat dilakukan menggunakan pintasan dinamis. Aplikasi mendorong pintasan dinamis setelah pengguna melakukan tindakan yang relevan, seperti membuat catatan baru di aplikasi pelacakan tugas. Dengan Action Aplikasi, Anda mengaktifkan pintasan ini untuk suara dengan mengikatnya ke BII sehingga pengguna dapat mengakses kontennya dari Asisten dengan mengucapkan hal-hal seperti, "Ok Google, buka daftar belanja saya di ExampleApp".

Tiga layar progresif menampilkan Asisten Google meluncurkan pintasan dinamis.

Gambar 1. Tiga layar progresif menampilkan tugas yang dibuat pengguna, dan Asisten Google meluncurkan pintasan dinamis ke item tugas tersebut.

Yang akan Anda buat

Dalam codelab ini, Anda akan mengaktifkan pintasan dinamis untuk suara di aplikasi contoh pembuatan daftar tugas di Android, yang memungkinkan pengguna meminta Asisten untuk membuka item daftar tugas yang mereka buat di aplikasi. Anda melakukannya menggunakan pola arsitektur Android, khususnya pola repositori, pencari lokasi layanan, dan ViewModel.

Prasyarat

Codelab ini dibuat berdasarkan konsep Action Aplikasi yang dibahas di codelab sebelumnya, terutama pintasan statis dan BII. Jika Anda baru menggunakan Action Aplikasi, sebaiknya selesaikan codelab tersebut sebelum melanjutkan.

Selain itu, pastikan lingkungan pengembangan Anda memiliki konfigurasi berikut sebelum melanjutkan:

  • Terminal untuk menjalankan perintah shell dengan git terinstal.
  • Rilis stabil terbaru dari Android Studio.
  • Perangkat Android fisik atau virtual dengan akses Internet.
  • Akun Google yang login ke Android Studio, aplikasi Google, dan aplikasi Asisten Google.

2. Memahami cara kerjanya

Mengaktifkan pintasan dinamis untuk Voice Access melibatkan langkah-langkah berikut:

  • Mengikat pintasan dinamis ke BII yang memenuhi syarat.
  • Memungkinkan Asisten menyerap pintasan dengan menambahkan library Integrasi Pintasan Google.
  • Mendorong pintasan setiap kali pengguna menyelesaikan tugas dalam aplikasi yang relevan.

Mengikat pintasan

Agar pintasan dinamis dapat diakses dari Asisten, pintasan tersebut harus terikat ke BII yang relevan. Saat BII dengan pintasan dipicu, Asisten mencocokkan parameter di permintaan pengguna dengan kata kunci yang ditentukan di pintasan terikat. Contoh:

  • Pintasan yang terikat ke BII GET_THING memungkinkan pengguna meminta konten dalam aplikasi tertentu, langsung dari Asisten. * "Ok Google, buka daftar belanja saya di ExampleApp".
  • Pintasan yang terikat ke BII ORDER_MENU_ITEM memungkinkan pengguna memutar ulang pesanan sebelumnya. * "Ok Google, pesan seperti biasa dari ExampleApp".

Lihat Referensi intent bawaan untuk melihat kategori daftar lengkap BII.

Menyediakan pintasan ke Asisten

Setelah mengikat pintasan ke BII, langkah berikutnya adalah mengaktifkan Asisten untuk menyerap pintasan ini dengan menambahkan library Integrasi Pintasan Google ke project Anda. Dengan library ini, Asisten akan mengetahui setiap pintasan yang didorong oleh aplikasi Anda, yang memungkinkan pengguna meluncurkan pintasan tersebut dengan menggunakan frasa pemicu pintasan di Asisten.

3. Menyiapkan lingkungan pengembangan

Codelab ini menggunakan aplikasi daftar tugas contoh yang dibuat untuk Android. Dengan aplikasi ini, pengguna dapat menambahkan item ke daftar, menelusuri item daftar tugas menurut kategori, dan memfilter tugas menurut status penyelesaiannya. Download dan persiapkan aplikasi contoh dengan menyelesaikan bagian ini.

Mendownload file dasar

Jalankan perintah berikut untuk meng-clone repositori GitHub aplikasi contoh:

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

Setelah meng-clone repositori, ikuti langkah-langkah berikut untuk membukanya di Android Studio:

  1. Dalam dialog Welcome to Android Studio, klik Import project.
  2. Pilih folder tempat Anda meng-clone repositori.

Atau, Anda dapat melihat versi aplikasi contoh yang mewakili codelab yang sudah selesai dengan meng-clone cabang codelab-complete dari repo GitHub-nya:

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

Memperbarui ID aplikasi Android

Memperbarui ID aplikasi akan mengidentifikasi aplikasi di perangkat pengujian Anda secara unik dan menghindari error "Nama paket duplikat" jika aplikasi diupload ke Konsol Play. Untuk memperbarui ID aplikasi, buka app/build.gradle:

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

Ganti "MYUNIQUENAME" di kolom applicationId menjadi sesuatu yang unik bagi Anda.

Menambahkan dependensi Shortcuts API

Tambahkan library Jetpack berikut ke file resource 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'
   ...
}

Menguji aplikasi di perangkat Anda

Sebelum membuat lebih banyak perubahan pada aplikasi, sebaiknya Anda mengetahui apa saja yang dapat dilakukan aplikasi contoh. Untuk menjalankan aplikasi di emulator, ikuti langkah-langkah berikut:

  1. Di Android Studio, pilih Run > Run app atau klik RunMenjalankan ikon aplikasi di Android Studio di toolbar.
  2. Dalam dialog Select Deployment Target, pilih perangkat lalu klik OK. Versi OS yang direkomendasikan adalah Android 10 (API level 30) atau lebih tinggi, meskipun Action Aplikasi dapat berfungsi di perangkat yang menjalankan Android 5 (API level 21).
  3. Tekan lama tombol Home untuk menyiapkan Asisten dan memastikannya berfungsi. Anda harus login ke Asisten di perangkat jika belum melakukannya.

Untuk informasi selengkapnya tentang perangkat virtual Android, lihat Membuat dan mengelola perangkat virtual.

Jelajahi aplikasi secara singkat untuk melihat apa yang dapat dilakukannya. Dengan mengetuk ikon Plus, Anda akan membuat item tugas baru, dan item menu di kanan atas memungkinkan Anda menelusuri dan memfilter item tugas menurut status penyelesaian.

4. Membuat class repositori pintasan

Beberapa class dalam aplikasi contoh akan memanggil API ShortcutManagerCompat untuk mendorong dan mengelola pintasan dinamis. Untuk mengurangi redundansi kode, Anda akan menerapkan repositori agar class project Anda dapat mengelola pintasan dinamis dengan mudah.

Pola desain repositori menyediakan API yang bersih untuk mengelola pintasan. Keuntungan bagi repositori adalah detail API dasar diabstraksi secara seragam di belakang API minimal. Terapkan repositori dengan mengikuti langkah-langkah berikut:

  1. Buat class ShortcutsRepository untuk mengabstrak API ShortcutManagerCompat.
  2. Tambahkan metode ShortcutsRepository ke pencari lokasi layanan aplikasi.
  3. Daftarkan layanan ShortcutRepository di Aplikasi utama.

Membuat repositori

Buat class Kotlin baru bernama ShortcutsRepository di paket com.example.android.architecture.blueprints.todoapp.data.source. Anda dapat menemukan paket ini tersusun dalam folder app/src/main/java. Anda akan menggunakan class ini untuk menerapkan antarmuka yang menyediakan serangkaian metode minimal yang menjelaskan kasus penggunaan codelab.

Jendela Android Studio menampilkan lokasi class ShortcutsRepository.

Gambar 2. Jendela Project Files Android Studio menampilkan lokasi class ShortcutsRepository.

Tempel kode berikut ke dalam class baru:

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

Selanjutnya, perbarui metode pushShortcut untuk memanggil API ShortcutManagerCompat. Perbarui class ShortcutsRepository dengan kode berikut:

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

Dalam contoh kode sebelumnya, kami meneruskan appContext ke API. Ini adalah properti class yang menyimpan Konteks Aplikasi. Anda harus menggunakan Konteks Aplikasi (bukan Konteks Aktivitas) untuk menghindari kebocoran memori, karena konteksnya mungkin dipertahankan lebih lama daripada siklus proses aktivitas host.

Selain itu, API mengharuskan kami meneruskan objek ShortcutInfoCompat untuk objek Task. Dalam contoh kode sebelumnya, kami dapat melakukannya dengan memanggil metode pribadi createShortcutCompat, yang akan kami perbarui untuk membuat dan menampilkan objek ShortcutInfoCompat. Untuk melakukannya, perbarui stub createShortcutCompat dengan kode berikut:

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

Sisa stub fungsi di class ini berkaitan dengan pembaruan dan penghapusan pintasan dinamis. Aktifkan fungsi tersebut dengan memperbaruinya menggunakan kode berikut:

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

Menambahkan class ke pencari lokasi layanan

Setelah class ShortcutsRepository dibuat, langkah berikutnya adalah menyediakan objek ber-instance dari class ini untuk seluruh aplikasi. Aplikasi ini mengelola dependensi class dengan menerapkan pola pencari lokasi layanan. Buka class pencari lokasi layanan menggunakan browser class di Android Studio dengan membuka Navigate > Class dan mengetik "ServiceLocator". Klik file Kotlin yang dihasilkan untuk membukanya di IDE Anda.

Di bagian atas ServiceLocator.kt, tempel kode berikut untuk mengimpor paket ShortcutsRepository dan 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

Tambahkan anggota dan metode layanan ShortcutRepository dengan menempelkan kode berikut ke dalam isi 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)
       }
   }
 }

Mendaftarkan layanan pintasan

Langkah terakhir adalah mendaftarkan layanan ShortcutsRepository baru Anda ke Aplikasi. Di Android Studio, buka TodoApplication.kt dan salin kode berikut di dekat bagian atas file:

TodoApplication.kt

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

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

Selanjutnya, daftarkan layanan dengan menambahkan kode berikut ke isi class:

TodoApplication.kt

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

   //...

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

   //...
}

Buat aplikasi dan pastikan aplikasi terus berjalan.

5. Mendorong pintasan baru

Setelah layanan pintasan dibuat, Anda siap untuk mulai mendorong pintasan. Karena pengguna membuat konten (item tugas) di aplikasi ini dan berharap dapat melihatnya lagi nanti, kami akan mengaktifkan akses melalui suara ke konten ini dengan mendorong pintasan dinamis yang terikat ke BII GET_THING setiap kali pengguna membuat tugas baru. Hal ini memungkinkan Asisten membawa pengguna langsung ke item tugas yang diminta saat mereka memicu BII dengan meminta hal-hal seperti, "Ok Google, buka daftar belanjaan saya di SampleApp."

Anda dapat mengaktifkan fungsi ini di aplikasi contoh dengan menyelesaikan langkah-langkah berikut:

  1. Mengimpor layanan ShortcutsRepository ke class AddEditTaskViewModel, yang bertanggung jawab untuk mengelola objek daftar tugas.
  2. Mendorong pintasan dinamis saat pengguna membuat tugas baru.

Mengimpor ShortcutsRepository

Pertama-tama, kami harus menyediakan layanan ShortcutsRepository untuk AddEditTaskViewModel. Untuk melakukannya, impor layanan ke ViewModelFactory, class factory yang digunakan aplikasi untuk membuat instance objek ViewModel, termasuk AddEditTaskViewModel.

Buka browser kelas di Android Studio dengan membuka Navigate > Class dan mengetik "ViewModelFactory". Klik file Kotlin yang dihasilkan untuk membukanya di IDE Anda.

Di bagian atas ViewModelFactory.kt, tempel kode berikut untuk mengimpor paket ShortcutsRepository dan SuppressLint:

ViewModelFactory.kt

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

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

Selanjutnya, ganti isi ViewModelFactory dengan kode berikut:

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
}

Selesaikan perubahan ViewModelFactory dengan naik satu lapisan, dan teruskan ShortcutsRepository ke konstruktor factory. Buka browser file Android Studio dengan membuka Navigate > File dan mengetik "FragmentExt.kt". Klik file Kotlin yang dihasilkan yang terletak di paket util untuk membukanya di IDE Anda.

Ganti isi FragmentExt.kt dengan kode berikut:

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

Mendorong pintasan

Dengan class abstraksi ShortcutsRepository yang tersedia untuk class ViewModel aplikasi contoh, Anda akan memperbarui AddEditTaskViewModel, class ViewModel yang bertanggung jawab untuk membuat catatan, guna mendorong pintasan dinamis setiap kali pengguna membuat catatan baru.

Di Android Studio, buka browser kelas dan ketik "AddEditTaskViewModel". Klik file Kotlin yang dihasilkan untuk membukanya di IDE Anda.

Pertama, tambahkan paket ShortcutsRepository ke class ini dengan pernyataan impor berikut:

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

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

Selanjutnya, tambahkan properti class shortcutsRepository dengan memperbarui konstruktor class dengan kode berikut:

AddEditTaskViewModel.kt

//...

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

    //...

Setelah class ShortcutsRepository ditambahkan, buat fungsi baru, pushShortcut(), untuk memanggil class ini. Tempel fungsi pribadi berikut ke dalam isi AddEditTaskViewModel:

AddEditTaskViewModel.kt

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

Terakhir, dorong pintasan dinamis baru setiap kali tugas dibuat. Ganti konten fungsi saveTask() dengan kode berikut:

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

Menguji kode Anda

Akhirnya kami siap menguji kode. Pada langkah ini, Anda mendorong pintasan dinamis yang diaktifkan suara dan memeriksanya menggunakan aplikasi Asisten Google.

Membuat pratinjau

Membuat pratinjau menggunakan plugin Asisten Google memungkinkan pintasan dinamis Anda muncul di Asisten pada perangkat pengujian Anda.

Menginstal plugin pengujian

Jika Anda belum memiliki plugin Asisten Google, instal dengan mengikuti langkah-langkah berikut di Android Studio:

  1. Buka **File > Settings (Android Studio > Preferences di MacOS).
  2. Di bagian Plugin, buka Marketplace dan telusuri "Google Assistant".
  3. Instal alat tersebut, lalu mulai ulang Android Studio.

Membuat pratinjau

Buat pratinjau dengan mengikuti langkah-langkah berikut di Android Studio:

  1. Klik Tools > Google Assistant > "App Actions Test Tool".
  2. Di kotak App name, tentukan nama seperti "Todo List".
  3. Klik Create Preview. Jika diminta, tinjau dan setujui kebijakan dan persyaratan layanan Action Aplikasi.

Panel pembuatan pratinjau Alat Pengujian Action Aplikasi.

Gambar 3. Panel pembuatan pratinjau Alat Pengujian Action Aplikasi.

Selama pengujian, pintasan dinamis yang Anda dorong ke Asisten akan muncul di Asisten yang disusun berdasarkan App name yang Anda berikan untuk pratinjau.

Mendorong dan memeriksa pintasan

Luncurkan ulang aplikasi contoh di perangkat pengujian Anda dan lakukan langkah-langkah berikut:

  1. Buat tugas baru dengan judul "Mulai codelab"
  2. Buka aplikasi Asisten Google dan ucapkan atau ketikkan: "Pintasan saya".
  3. Ketuk tab Jelajahi. Anda akan melihat pintasan contoh.
  4. Ketuk pintasan untuk memanggilnya. Anda akan melihat aplikasi diluncurkan dengan nama pintasan yang diisi otomatis di kotak filter, sehingga menemukan item tugas yang diminta jadi lebih mudah.

6. (Opsional) Memperbarui dan menghapus pintasan

Selain mendorong pintasan dinamis baru saat runtime, aplikasi Anda juga dapat memperbaruinya untuk mencerminkan status konten dan preferensi pengguna saat ini. Sebaiknya perbarui pintasan yang ada setiap kali pengguna mengubah item tujuan, seperti mengganti nama tugas di aplikasi contoh. Anda juga harus menghapus pintasan yang sesuai setiap kali resource tujuan dihapus untuk menghindari ditampilkannya pintasan yang rusak kepada pengguna.

Memperbarui pintasan

Ubah AddEditTaskViewModel untuk memperbarui pintasan dinamis setiap kali pengguna mengubah detail item tugas. Pertama, perbarui isi class dengan kode berikut untuk menambahkan fungsi pembaruan yang menggunakan class repositori:

AddEditTaskViewModel.kt

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

Selanjutnya, ubah fungsi saveTask() untuk memanggil metode baru setiap kali tugas yang ada diperbarui.

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

Uji kode Anda dengan meluncurkan kembali aplikasi dan mengikuti langkah-langkah berikut:

  1. Ganti nama judul item tugas yang ada menjadi "Selesaikan codelab".
  2. Buka Asisten Google dengan mengucapkan, "Ok Google, pintasan saya".
  3. Ketuk tab Jelajahi. Anda akan melihat label singkat yang diperbarui untuk Pintasan pengujian Anda.

Menghapus pintasan

Pintasan aplikasi contoh akan dihapus setiap kali pengguna menghapus tugas. Dalam aplikasi contoh, logika penghapusan tugas berada di class TaskDetailViewModel. Sebelum memperbarui class ini, kami perlu memperbarui ViewModelFactory lagi untuk meneruskan shortcutsRepository ke TaskDetailViewModel.

Buka ViewModelFactory dan ganti konten metode konstruktornya dengan kode berikut:

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

Selanjutnya, buka TaskDetailViewModel. Impor modul ShortcutsRepository dan deklarasikan variabel instance menggunakan kode berikut:

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

Terakhir, ubah fungsi deleteTask() untuk memanggil shortcutsRepository guna menghapus pintasan berdasarkan ID-nya setiap kali tugas dengan taskId yang sesuai dihapus:

TaskDetailViewModel.kt

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

Untuk menguji kode Anda, luncurkan ulang aplikasi dan ikuti langkah-langkah berikut:

  1. Hapus tugas pengujian Anda.
  2. Ganti nama judul item tugas yang ada menjadi "Selesaikan codelab".
  3. Buka Asisten Google dengan mengucapkan, "Ok Google, pintasan saya".
  4. Ketuk tab Jelajahi. Konfirmasi bahwa pintasan pengujian Anda tidak lagi muncul.

7. Langkah berikutnya

Selamat! Berkat Anda, pengguna aplikasi contoh kami dapat dengan mudah kembali ke catatan yang mereka buat dengan meminta hal-hal seperti, "Ok Google, buka daftar belanja saya di ExampleApp" kepada Asisten. Pintasan mendorong engagement pengguna yang lebih dalam dengan memudahkan pengguna mengulang tindakan yang sering digunakan di aplikasi Anda.

Yang telah dibahas

Dalam codelab ini, Anda telah mempelajari cara:

  • Mengidentifikasi kasus penggunaan untuk mendorong pintasan dinamis di aplikasi.
  • Mengurangi kompleksitas kode menggunakan repositori, injeksi dependensi, dan pola desain pencari lokasi layanan.
  • Mendorong pintasan dinamis yang diaktifkan suara ke konten aplikasi buatan pengguna.
  • Memperbarui dan menghapus pintasan yang ada.

Langkah berikutnya

Dari sini, Anda dapat terus mencoba mengoptimalkan aplikasi Daftar Tugas. Untuk mereferensikan project yang sudah selesai, lihat cabang –codelab-complete repo di GitHub.

Berikut beberapa saran untuk mempelajari lebih lanjut cara memperluas aplikasi ini dengan Action Aplikasi:

Untuk melanjutkan perjalanan Actions on Google Anda, pelajari referensi berikut:

Ikuti kami di Twitter @ActionsOnGoogle untuk terus memantau pengumuman terbaru kami, dan kirim tweet dengan tagar #appActions untuk membagikan karya yang telah Anda buat.

Survei masukan

Terakhir, isi survei ini untuk memberikan masukan tentang pengalaman Anda dengan codelab ini.