הרחבת קיצורי הדרך הדינמיים ל-Google Assistant באמצעות 'פעולות באפליקציה'

הרחבת קיצורי הדרך הדינמיים ל-Google Assistant באמצעות 'פעולות באפליקציה'

מידע על Codelab זה

subjectהעדכון האחרון: ספט׳ 12, 2024
account_circleנכתב על ידי Google Assistant Developer Relations

1.‏ סקירה כללית

בcodelab הקודם השתמשתם במקשי קיצור סטטיים כדי להטמיע כוונות מובנות (BII) נפוצות באפליקציה לדוגמה. מפתחי Android משתמשים בפעולות באפליקציה כדי להרחיב את הפונקציונליות של האפליקציה ל-Google Assistant.

קיצורי דרך סטטיים נכללים באפליקציה, וניתן לעדכן אותם רק על ידי פרסום גרסאות חדשות של האפליקציה. כדי להפעיל פונקציונליות קולית לרכיבים דינמיים באפליקציה, כמו תוכן שנוצר על ידי משתמשים, משתמשים בקיצורי דרך דינמיים. אפליקציות שולחות קיצורי דרך דינמיים אחרי שהמשתמשים מבצעים פעולות רלוונטיות, כמו יצירת הערה חדשה באפליקציה למעקב אחרי משימות. באמצעות פעולות באפליקציות, אפשר להפעיל את קיצורי הדרך האלה לקול על ידי קישורם ל-BII, וכך לאפשר למשתמשים לגשת לתוכן שלהם מ-Assistant באמצעות משפטים כמו "Ok Google, open my grocery list on ExampleApp".

שלושה מסכים מתקדמים שבהם מוצגת Google Assistant שמפעילה קיצור דרך דינמי.

איור 1. שלושה מסכים מתקדמים שמוצגת בהם משימה שנוצרה על ידי משתמש, ו-Google Assistant מפעילה קיצור דרך דינמי לפריט המשימה הזה.

מה תפַתחו

בקודלאב הזה תפעילו קיצורי דרך דינמיים לקול באפליקציית טודו-ליסט לדוגמה ל-Android, כדי לאפשר למשתמשים לבקש מ-Assistant לפתוח את הפריטים ברשימת המשימות שהם יוצרים באפליקציה. כדי לעשות זאת, תשתמשו בתבניות ארכיטקטורה של Android, ובמיוחד בתבניות של מאגר, שירות לאיתור ו-ViewModel.

דרישות מוקדמות

סדנת הקוד הזו מבוססת על המושגים של פעולות באפליקציות שסופקו בסדנת הקוד הקודמת, במיוחד על מודעות BIIs ומקשי קיצור סטטיים. אם עוד לא השתמשתם ב'פעולות באפליקציה', מומלץ להשלים את הפעולה הזו לפני שממשיכים.

בנוסף, לפני שממשיכים, צריך לוודא שבסביבת הפיתוח יש את ההגדרות הבאות:

  • טרמינל להרצת פקודות מעטפת עם git מותקן.
  • הגרסה היציבה האחרונה של Android Studio.
  • מכשיר Android פיזי או וירטואלי עם גישה לאינטרנט.
  • חשבון Google שמחובר ל-Android Studio, לאפליקציית Google ולאפליקציית Google Assistant.

2.‏ איך זה עובד

כדי להפעיל קיצור דרך דינמי לגישה קולית:

קיצורי דרך לקישורים

כדי שאפשר יהיה לגשת לקיצור דרך דינמי מ-Assistant, צריך לשייך אותו ל-BII רלוונטי. כשמתרחשת הפעלה של BII עם קיצור דרך, Assistant מתאימה פרמטרים בבקשה של המשתמש למילות מפתח שהוגדרו בקיצור הדרך המקושר. לדוגמה:

  • קיצור דרך שמקושר ל-BII של GET_THING יכול לאפשר למשתמשים לבקש תוכן ספציפי בתוך האפליקציה, ישירות מ-Assistant. * "Ok Google, open my grocery list on ExampleApp"
  • קיצור דרך שמקושר ל-BII‏ START_EXERCISE יכול לאפשר למשתמשים לראות את סשני האימון שלהם. * "Ok Google, Ask ExampleApp to start my organic activity. "

לרשימה מלאה של מזהי BII אפשר לעיין בחומר העזר בנושא כוונות מובנות.

מתן קיצורי דרך ל-Assistant

אחרי קישור קיצורי הדרך ל-BII, השלב הבא הוא לאפשר ל-Assistant להטמיע את קיצורי הדרך האלה על ידי הוספת ספריית השילוב של Google קיצורי דרך לפרויקט. כשהספרייה הזאת תהיה זמינה, Assistant תזהה את כל מקשי הקיצור שהאפליקציה שלך מפעילה, וכך המשתמשים יוכלו להפעיל את קיצורי הדרך האלה באמצעות ביטוי הטריגר של קיצור הדרך ב-Assistant.

3.‏ הכנת סביבת הפיתוח

ה-Codelab הזה משתמש בדוגמה של אפליקציה עם רשימת משימות שמיועדת ל-Android. באמצעות האפליקציה הזו, משתמשים יכולים להוסיף פריטים לרשימות, לחפש פריטים ברשימת המשימות לפי קטגוריה ולסנן משימות לפי סטטוס ההשלמה. ממלאים את הסעיף הזה כדי להוריד ולהכין את האפליקציה לדוגמה.

הורדת קובצי הבסיס

מריצים את הפקודה הבאה כדי לשכפל את מאגר הנתונים של האפליקציה לדוגמה ב-GitHub:

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

אחרי שמשכפלים את המאגר, פועלים לפי השלבים הבאים כדי לפתוח אותו ב-Android Studio:

  1. בתיבת הדו-שיח תחילת העבודה ב-Android Studio לוחצים על ייבוא פרויקט.
  2. בוחרים את התיקייה שבה קלונתם את המאגר.

לחלופין אפשר להציג גרסה של האפליקציה לדוגמה שמייצגת את ה-Codelab שהושלם על ידי שכפול ההסתעפות codelab-complete של מאגר ה-GitHub שלה:

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

עדכון המזהה של האפליקציה ל-Android

עדכון מזהה האפליקציה מאפשר לזהות את האפליקציה באופן ייחודי במכשיר הבדיקה, ומונעת את הודעת השגיאה 'שם החבילה כפול' אם האפליקציה תועלה ל-Play Console. כדי לעדכן את מזהה האפליקציה, פותחים את app/build.gradle:

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

מחליפים את 'MYUNIQUENAME' בשדה applicationId בשם ייחודי.

הוספת יחסי תלות של Shortcuts API

מוסיפים את ספריות Jetpack הבאות לקובץ המשאב 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'
   ...
}

בדיקת האפליקציה במכשיר

לפני שמבצעים שינויים נוספים באפליקציה, חשוב להבין מה אפשר לעשות באמצעות האפליקציה לדוגמה. כדי להפעיל את האפליקציה באמולטור שלכם, מבצעים את השלבים הבאים:

  1. ב-Android Studio, בוחרים באפשרות Run (הפעלה) > Run app (הפעלת אפליקציה) או לוחצים על Run (הפעלה)הפעלת סמל האפליקציה ב-Android Studio בסרגל הכלים.
  2. בתיבת הדו-שיח Select Deployment Target, בוחרים מכשיר ולוחצים על OK. גרסת מערכת ההפעלה המומלצת היא Android 10 (רמת API 30) ואילך, אבל פעולות האפליקציה פועלות במכשירים החל מ-Android 5 (רמת API 21).
  3. לוחצים לחיצה ארוכה על הלחצן הראשי כדי להגדיר את Assistant ולוודא שהיא פועלת. אם עדיין לא עשיתם זאת, תצטרכו להיכנס ל-Assistant במכשיר.

מידע נוסף על מכונות וירטואליות של Android זמין במאמר יצירה וניהול של מכונות וירטואליות.

בדקו בקצרה את האפליקציה כדי לראות מה היא יכולה לעשות. הקשה על סמל הפלוס יוצרת פריט חדש במשימה, ובעזרת האפשרויות בתפריט בפינה השמאלית העליונה אפשר לחפש ולסנן את המשימות לפי סטטוס ההשלמה.

4.‏ יצירת מחלקה למאגר קיצורי דרך

חלק מהכיתות באפליקציה לדוגמה שלנו יקראו ל-API של ShortcutManagerCompat כדי להעביר ולנהל קיצורי דרך דינמיים. כדי לצמצם את יתירות הקוד, תטמיעו מאגר כדי לאפשר למחלקות הפרויקטים לנהל בקלות קיצורי דרך דינמיים.

תבנית העיצוב של מאגר מספקת API נקי לניהול קיצורי דרך. היתרון של המאגר הוא שהפרטים של ה-API הבסיסי מופשטים באופן אחיד מאחורי API מינימלי. כדי להטמיע את המאגר:

  1. יוצרים מחלקה ShortcutsRepository כדי להפשט את ה-API של ShortcutManagerCompat.
  2. מוסיפים שיטות ShortcutsRepository למאתר השירותים של האפליקציה.
  3. רושמים את השירות ShortcutRepository באפליקציה הראשית.

יצירת המאגר

יוצרים בכיתה Kotlin חדשה בשם ShortcutsRepository בחבילה com.example.android.architecture.blueprints.todoapp.data.source. החבילה הזו מאורגנת בתיקייה app/src/main/java. בכיתה הזו נשתמש כדי להטמיע ממשק שמספק קבוצה מינימלית של שיטות שכוללות את התרחיש לדוגמה ב-codelab.

חלון Android Studio שבו מוצג המיקום של הכיתה ShortcutsRepository.

איור 2. חלון קבצים של פרויקט ב-Android Studio שבו מוצג המיקום של הכיתה ShortcutsRepository.

מדביקים את הקוד הבא בכיתה החדשה:

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

בשלב הבא, מעדכנים את ה-method pushShortcut כדי להפעיל את ה-API של ShortcutManagerCompat. מעדכנים את הכיתה ShortcutsRepository באמצעות הקוד הבא:

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

בדוגמת הקוד הקודמת העברנו את הערך appContext ל-API. זהו מאפיין של הכיתה שמכיל Application Context. חשוב להשתמש בApplication Context (לעומת Activity Context) כדי למנוע דליפות זיכרון, כי יכול להיות שההקשר יישמר למשך זמן ארוך יותר ממחזור החיים של פעילות המארח.

בנוסף, ה-API דורש שנעביר אובייקט ShortcutInfoCompat עבור אובייקט המשימה. בדוגמת הקוד הקודמת, ניתן לעשות זאת באמצעות קריאה לשיטה הפרטית createShortcutCompat, שאותה נעדכן כדי ליצור ולהחזיר אובייקט ShortcutInfoCompat. כדי לעשות זאת, צריך לעדכן את ה-stub של createShortcutCompat עם הקוד הבא:

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

שאר stubs הפונקציות בכיתה הזו עוסקים בעדכון ובמחיקה של קיצורי דרך דינמיים. כדי להפעיל את הפונקציות האלה, צריך לעדכן אותן באמצעות הקוד הבא:

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

הוספת מחלקה למאתר השירותים

אחרי שיוצרים את הכיתה ShortcutsRepository, השלב הבא הוא להפוך אובייקטים של הכיתה הזו שיצרו זמינים לשאר האפליקציה. האפליקציה הזו מנהלת את יחסי התלות בין הכיתות על ידי הטמעת התבנית service locator. פותחים את הכיתה של מאתר השירותים באמצעות דפדפן הכיתות ב-Android Studio. לשם כך, עוברים אל Navigate (ניווט) > Class (כיתה) ומקלידים ServiceLocator. לוחצים על קובץ ה-Kotlin שנוצר כדי לפתוח אותו בסביבת הפיתוח המשולבת.

בחלק העליון של ServiceLocator.kt, מדביקים את הקוד הבא כדי לייבא את החבילות ShortcutsRepository ו-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

מוסיפים את המשתנים והשיטות של השירות ShortcutRepository על ידי הדבקת הקוד הבא בגוף של 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)
       }
   }
 }

רישום שירות קיצור הדרך

השלב האחרון הוא רישום של שירות ShortcutsRepository החדש שלך באפליקציה. ב-Android Studio, פותחים את הקובץ TodoApplication.kt ומעתיקים את הקוד הבא לחלק העליון של הקובץ:

TodoApplication.kt

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

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

בשלב הבא, מוסיפים את הקוד הבא לגוף הכיתה כדי לרשום את השירות:

TodoApplication.kt

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

   //...

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

   //...
}

יוצרים את האפליקציה ומוודאים שהיא ממשיכה לפעול.

5.‏ שליחת קיצור דרך חדש

אחרי יצירת השירות לקיצורי הדרך, ניתן להתחיל להעביר קיצורי דרך. מכיוון שהמשתמשים יוצרים תוכן (פריטי משימות) באפליקציה הזו ומצפים שיוכלו לחזור אליו מאוחר יותר, נפעיל את הגישה לתוכן הזה באמצעות קול על ידי לחיצה על קיצור דרך דינמי שמקושר ל-BII של GET_THING בכל פעם שמשתמש יוצר משימה חדשה. כך Assistant יכולה להפעיל את המשתמשים ישירות לפריט המשימה המבוקש כשהם מפעילים את ה-BII באמצעות פקודות כמו "Ok Google, open my shopping list on SampleApp".

כדי להפעיל את הפונקציונליות הזו באפליקציה לדוגמה, מבצעים את השלבים הבאים:

  1. ייבוא השירות ShortcutsRepository לכיתה AddEditTaskViewModel, שאחראית לניהול אובייקטים של רשימות משימות.
  2. דחיפת קיצור דרך דינמי כשהמשתמש יוצר משימה חדשה.

ייבוא של ShortcutsRepository

קודם צריך להפוך את השירות ShortcutsRepository לזמין ל-AddEditTaskViewModel. כדי לעשות זאת, מייבאים את השירות אל ViewModelFactory, רמת היצרן שהאפליקציה משתמשת בה כדי ליצור אובייקטים של ViewModel, כולל AddEditTaskViewModel.

כדי לפתוח את דפדפן הכיתה ב-Android Studio, עוברים לקטע ניווט > כיתה וההקלדה של "ViewModel חוקיים". לוחצים על קובץ ה-Kotlin שנוצר כדי לפתוח אותו בסביבת הפיתוח המשולבת.

בחלק העליון של ViewModelFactory.kt, מדביקים את הקוד הבא כדי לייבא את החבילות ShortcutsRepository ו-SuppressLint:

ViewModelFactory.kt

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

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

לאחר מכן, מחליפים את הגוף של ViewModelFactory בקוד הבא:

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
}

כדי לסיים את השינויים ב-ViewModelFactory, עוברים שכבה אחת למעלה ומעבירים את ShortcutsRepository למבנה ה-constructor של המפעל. פותחים את הדפדפן לקבצים של Android Studio על ידי מעבר אל ניווט > קובץ מקלידים "FragmentExt.kt". לוחצים על קובץ ה-Kotlin שנוצר, שנמצא בחבילה util, כדי לפתוח אותו בסביבת הפיתוח המשולבת.

מחליפים את הגוף של FragmentExt.kt בקוד הבא:

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

לחיצה על קיצור דרך

כאשר מעבירים את מחלקת העיצוב ShortcutsRepository למחלקות ViewModel של האפליקציה לדוגמה, אפשר לעדכן את AddEditTaskViewModel, מחלקת ViewModel שאחראית ליצירת הערות, כדי לדחוף קיצור דרך דינמי בכל פעם שמשתמש יוצר פתק חדש.

ב-Android Studio, פותחים את דפדפן הכיתות ומקלידים AddEditTaskViewModel. לוחצים על קובץ ה-Kotlin שנוצר כדי לפתוח אותו בסביבת הפיתוח המשולבת.

קודם כול, מוסיפים את החבילה ShortcutsRepository לכיתה הזו באמצעות הצהרת הייבוא הבאה:

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

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

בשלב הבא, מוסיפים את מאפיין הכיתה shortcutsRepository על ידי עדכון ה-constructor של הכיתה באמצעות הקוד הבא:

AddEditTaskViewModel.kt

//...

/**
*
ViewModel for the Add/Edit screen.
*/

class AddEditTaskViewModel(
   private val tasksRepository: TasksRepository,
   private val shortcutsRepository: ShortcutsRepository
) : ViewModel() {

    //...

אחרי הוספת המחלקה ShortcutsRepository, אפשר ליצור פונקציה חדשה, pushShortcut(), כדי לקרוא לכיתה הזו. מדביקים את הפונקציה הפרטית הבאה בגוף של AddEditTaskViewModel:

AddEditTaskViewModel.kt

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

לבסוף, אפשר לדחוף קיצור דרך דינמי חדש בכל פעם שנוצרת משימה. מחליפים את התוכן של פונקציית saveTask() בקוד הבא:

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

בדיקת הקוד

סוף סוף אנחנו מוכנים לבדוק את הקוד שלנו! בשלב הזה, מפעילים קיצור דרך דינמי עם הפעלה קולית ובודקים אותו באמצעות אפליקציית Google Assistant.

יצירת קטע מקדים

יצירת גרסת טרום-השקה באמצעות הפלאגין של Google Assistant מאפשרת לקיצורי הדרך הדינמיים להופיע ב-Assistant במכשיר הבדיקה.

התקנת הפלאגין לבדיקה

אם עדיין לא התקנתם את הפלאגין של Google Assistant, צריך לבצע את הפעולות הבאות ב-Android Studio כדי להתקין אותו:

  1. מעבר אל **קובץ > 'הגדרות' (Android Studio > 'העדפות' ב-MacOS).
  2. בקטע Plugins (פלאגינים), עוברים אל Marketplace (זירת מסחר) ומחפשים את 'Google Assistant'.
  3. מתקינים את הכלי ומפעילים מחדש את Android Studio.

יצירת התצוגה המקדימה

כדי ליצור תצוגה מקדימה ב-Android Studio:

  1. לוחצים על כלים > Google Assistant > "כלי הבדיקה של פעולות באפליקציה".
  2. בתיבה שם האפליקציה, מגדירים שם כמו "רשימת משימות".
  3. לוחצים על Create Preview. אם מופיעה בקשה, קוראים את המדיניות ואת התנאים וההגבלות של 'פעולות באפליקציה' ומאשרים אותם.

חלונית ליצירת תצוגה מקדימה של App Actions Test Tool.

איור 3. חלונית היצירה של תצוגה מקדימה בכלי לבדיקת פעולות באפליקציות.

במהלך הבדיקה, קיצורי דרך דינמיים שלוחצים על ה-Assistant מוצגים ב-Assistant לפי שם האפליקציה שסיפקתם בשביל התצוגה המקדימה.

דחיפה ובדיקה של קיצור דרך

מפעילים מחדש את האפליקציה לדוגמה במכשיר הבדיקה ופועלים לפי השלבים הבאים:

  1. יוצרים משימה חדשה עם השם 'התחלת הקודלהב'
  2. פותחים את אפליקציית Google Assistant ואומרים או מקלידים: "My shortcuts" (קיצורי הדרך שלי).
  3. מקישים על הכרטיסייה מה חדש. קיצור הדרך לדוגמה אמור להופיע.
  4. מקישים על קיצור הדרך כדי להפעיל אותו. האפליקציה אמורה להיפתח עם שם קיצור הדרך שמאוכלס מראש בתיבת הסינון, כך שיהיה קל למצוא את פריט המשימה המבוקש.

6.‏ (אופציונלי) עדכון ומחיקה של קיצור דרך

בנוסף להעברה של קיצורי דרך דינמיים חדשים בזמן הריצה, האפליקציה יכולה לעדכן אותם כך שישקפו את המצב הנוכחי של תוכן המשתמש וההעדפות שלו. מומלץ לעדכן קיצורי דרך קיימים בכל פעם שמשתמש משנה את פריט היעד, למשל שינוי השם של משימה באפליקציה לדוגמה שלנו. כמו כן, צריך למחוק קיצור דרך תואם בכל פעם שמסירים את משאב היעד, כדי למנוע הצגת קיצורי דרך לא תקינים למשתמשים.

עדכון קיצור דרך

אפשר לשנות את AddEditTaskViewModel כך שקיצור דרך דינמי יתעדכן בכל פעם שמשתמש משנה את הפרטים של פריט משימה. קודם כל, מעדכנים את גוף הכיתה באמצעות הקוד הבא כדי להוסיף פונקציית עדכון שמשתמשת בכיתה של המאגר:

AddEditTaskViewModel.kt

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

בשלב הבא, משנים את הפונקציה saveTask() כך שתפעיל את השיטה החדשה בכל פעם שמתעדכן פריט עבודה קיים.

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

כדי לבדוק את הקוד, מפעילים מחדש את האפליקציה ופועלים לפי השלבים הבאים:

  1. משנים את השם של פריט המשימה הקיים ל-Finish Codelab.
  2. כדי לפתוח את Google Assistant, אומרים "Ok Google, my shortcuts".
  3. מקישים על הכרטיסייה מה חדש. אמורה להופיע תווית קצרה מעודכנת של קיצור הדרך לבדיקה.

הסרת קיצור דרך

צריך להסיר את קיצורי הדרך לדוגמה של האפליקציות בכל פעם שמשתמש מוחק משימה. באפליקציה לדוגמה, הלוגיקה של מחיקת המשימות נמצאת במחלקה TaskDetailViewModel. לפני שנעדכן את הכיתה הזו, עלינו לעדכן שוב את ההרשאה ViewModelFactory כדי להעביר את shortcutsRepository אל TaskDetailViewModel.

פותחים את ViewModelFactory ומחליפים את התוכן של שיטת ה-constructor שלה בקוד הבא:

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

בשלב הבא, פותחים את TaskDetailViewModel. מייבאים את המודול ShortcutsRepository ומצהירים על משתנה מופע עבורו באמצעות הקוד הבא:

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

לסיום, אפשר לשנות את הפונקציה deleteTask() כך שתפעילי את shortcutsRepository, כך שקיצור הדרך יוסר מהמזהה שלו בכל פעם שמשימה עם taskId תואמת:

TaskDetailViewModel.kt

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

כדי לבדוק את הקוד, צריך להפעיל מחדש את האפליקציה ולפעול לפי השלבים הבאים:

  1. מוחקים את משימה הבדיקה.
  2. משנים את השם של פריט המשימה הקיים ל'סיום הקודלה'.
  3. כדי לפתוח את Google Assistant, אומרים "Ok Google, my shortcuts".
  4. מקישים על הכרטיסייה מה חדש. מוודאים שקיצור הדרך לבדיקה לא מופיע יותר.

7.‏ השלבים הבאים

מזל טוב! בזכותך, משתמשי האפליקציה לדוגמה שלנו יכולים לחזור בקלות לפתקים שהם יצרו ולבקש מ-Assistant לעשות דברים כמו "Ok Google, open my shopping list on ExampleApp". קיצורי דרך מעודדים מעורבות עמוקה יותר של המשתמשים כי הם מאפשרים למשתמשים לחזור בקלות על פעולות שהם עשו באפליקציה שלכם לעיתים קרובות.

אילו נושאים דיברנו?

ב-Codelab הזה למדת איך:

  • תרחישים לדוגמה של שליחת קיצורי דרך דינמיים באפליקציה.
  • צמצום המורכבות של הקוד באמצעות תבניות תכנון של מאגרים, הזרקת יחסי תלות ומאתרי שירותים.
  • דחיפת קיצורי דרך דינמיים שמופעלים באמצעות קול לתוכן אפליקציה שנוצר על ידי משתמשים.
  • לעדכן ולהסיר את קיצורי הדרך הקיימים.

מה השלב הבא?

מכאן אפשר לנסות לבצע שיפורים נוספים באפליקציה 'רשימת משימות'. כדי להפנות לפרויקט המוגמר, ראו הסתעפות Codelab-complete במאגר GitHub.

בהמשך מופיעות כמה הצעות ללמידה נוספת בנוגע להרחבת האפליקציה הזו באמצעות 'פעולות באפליקציה':

כדי להמשיך את התהליך של יצירת הפעולות ב-Google, כדאי לעיין במקורות המידע הבאים:

מומלץ לעקוב אחרינו ב-Twitter‏ ‎@ActionsOnGoogle כדי להתעדכן בהכרזות האחרונות שלנו, ולציוץ עם התג ‎#appActions כדי לשתף את מה שיצרתם.

סקר משוב

לסיום, נשמח לקבל ממך משוב על החוויה שלך ב-codelab הזה. אפשר למלא את הסקר הזה.