Uygulama İşlemleri ile dinamik kısayolları Google Asistan'a genişletme

1. Genel Bakış

Önceki codelab'de, örnek bir uygulamada sık kullanılan yerleşik amaçları (BII) uygulamak için statik kısayolları kullandınız. Android geliştiriciler, uygulama işlevselliğini Google Asistan'a genişletmek için uygulama işlemleri kullanır.

Statik kısayollar bir uygulamayla birlikte paketlenir ve yalnızca uygulamanın yeni sürümleri yayınlanarak güncellenebilir. Bir uygulamadaki kullanıcı tarafından oluşturulan içerik gibi dinamik öğeler için ses işlevinin etkinleştirilmesi dinamik kısayollar kullanılarak gerçekleştirilir. Uygulamalar, kullanıcılar görev izleme uygulamasında yeni not oluşturma gibi alakalı işlemler gerçekleştirdikten sonra dinamik kısayolları gönderir. Uygulama İşlemleri ile bu kısayolları bir BII'ye bağlayarak sesli olarak etkinleştirirsiniz. Böylece kullanıcılar, "Ok Google, ExampleApp'te alışveriş listemi aç" gibi ifadelerle içeriklerine Asistan'dan erişebilir.

Google Asistan'ın dinamik kısayol başlattığını gösteren üç aşamalı ekran.

Şekil 1. Kullanıcı tarafından oluşturulan bir görevi gösteren üç aşamalı ekran ve Google Asistan'ın bu görev öğesine yönelik dinamik bir kısayol başlatması.

Ne oluşturacaksınız?

Bu codelab'de, örnek bir yapılacaklar listesi Android uygulamasında ses için dinamik kısayolları etkinleştirerek kullanıcıların Asistan'dan uygulamada oluşturdukları görev listesi öğelerini açmasını sağlayacaksınız. Bunu, Android mimari kalıplarını (özellikle repository, service locator ve ViewModel kalıplarını) kullanarak yapacaksınız.

Ön koşullar

Bu codelab, önceki codelab'de ele alınan uygulama işlemleri kavramları, özellikle de BII'ler ve statik kısayollar üzerine kuruludur. Uygulama İşlemleri'ni ilk kez kullanıyorsanız devam etmeden önce bu codelab'i tamamlamanızı öneririz.

Ayrıca, devam etmeden önce geliştirme ortamınızın aşağıdaki yapılandırmaya sahip olduğundan emin olun:

  • Git'in yüklü olduğu kabuk komutlarını çalıştırmak için bir terminal.
  • Android Studio'nun en son kararlı sürümü.
  • İnternet erişimi olan fiziksel veya sanal bir Android cihaz.
  • Android Studio, Google uygulaması ve Google Asistan uygulamasında oturum açmış bir Google Hesabı

2. İşleyiş şeklini anlama

Sesli erişim için dinamik kısayol etkinleştirmek üzere aşağıdaki adımları uygulayın:

Bağlama kısayolları

Dinamik bir kısayolun Asistan'dan erişilebilir olması için ilgili bir BII'ye bağlı olması gerekir. Kısayolu olan bir BII tetiklendiğinde Asistan, kullanıcı isteğindeki parametreleri bağlı kısayolda tanımlanan anahtar kelimelerle eşleştirir. Örneğin:

  • GET_THING BII'ye bağlı bir kısayol, kullanıcıların doğrudan Asistan'dan belirli uygulama içi içerik istemesine olanak tanıyabilir. * "Ok Google, ExampleApp'te market listemi aç."
  • START_EXERCISE BII'ye bağlı bir kısayol, kullanıcıların egzersiz oturumlarını görmesine olanak tanıyabilir. * "Ok Google, ExampleApp'ten her zamanki egzersizimi başlatmasını iste."

BII'lerin tam ve kategorize edilmiş listesi için Yerleşik amaç referansı'na bakın.

Asistan'a kısayollar sağlama

Kısayollarınızı bir BII'ye bağladıktan sonraki adım, projenize Google Kısayol Entegrasyonu kitaplığını ekleyerek Asistan'ın bu kısayolları kullanmasını sağlamaktır. Bu kitaplık sayesinde Asistan, uygulamanız tarafından gönderilen her kısayoldan haberdar olur. Böylece kullanıcılar, Asistan'da kısayolun tetikleyici ifadesini kullanarak bu kısayolları başlatabilir.

3. Geliştirme ortamınızı hazırlama

Bu codelab'de, Android için oluşturulmuş örnek bir yapılacaklar listesi uygulaması kullanılır. Bu uygulamayla kullanıcılar listelere öğe ekleyebilir, görev listesi öğelerini kategoriye göre arayabilir ve görevleri tamamlanma durumuna göre filtreleyebilir. Bu bölümü tamamlayarak örnek uygulamayı indirip hazırlayın.

Temel dosyalarınızı indirme

Örnek uygulamanın GitHub deposunu klonlamak için aşağıdaki komutu çalıştırın:

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

Depoyu klonladıktan sonra Android Studio'da açmak için aşağıdaki adımları uygulayın:

  1. Welcome to Android Studio (Android Studio'ya Hoş Geldiniz) iletişim kutusunda Import project'i (Projeyi içe aktar) tıklayın.
  2. Depoyu klonladığınız klasörü seçin.

Alternatif olarak, Github deposunun codelab-complete şubesini klonlayarak tamamlanmış codelab'i temsil eden örnek uygulamanın bir sürümünü görüntüleyebilirsiniz:

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

Android uygulama kimliğini güncelleme

Uygulamanın uygulama kimliğini güncellemek, uygulamayı test cihazınızda benzersiz bir şekilde tanımlar ve uygulama Play Console'a yüklenirse "Paket adı yineleniyor" hatasını önler. Uygulama kimliğini güncellemek için app/build.gradle uygulamasını açın:

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

applicationId alanındaki "MYUNIQUENAME" ifadesini size özel benzersiz bir ifadeyle değiştirin.

Kısayollar API bağımlılıklarını ekleme

app/build.gradle kaynak dosyasına aşağıdaki Jetpack kitaplıklarını ekleyin:

app/build.gradle

dependencies {
   ...
   // Shortcuts library
   implementation "androidx.core:core:1.6.0"
   implementation 'androidx.core:core-google-shortcuts:1.0.1'
   ...
}

Uygulamayı cihazınızda test etme

Uygulamada başka değişiklikler yapmadan önce örnek uygulamanın neler yapabileceği hakkında fikir edinmek faydalı olur. Uygulamayı emülatörünüzde çalıştırmak için aşağıdaki adımları uygulayın:

  1. Android Studio'da Run > Run app'i (Çalıştır > Uygulamayı çalıştır) seçin veya araç çubuğunda Run'ı (Çalıştır) Android Studio'da uygulamayı çalıştırma simgesi tıklayın.
  2. Select Deployment Target (Dağıtım Hedefi Seçin) iletişim kutusunda bir cihaz seçin ve OK'u (Tamam) tıklayın. Uygulama İşlemleri Android 5 (API düzeyi 21)'ten itibaren tüm cihazlarda çalışsa da önerilen OS sürümü Android 10 (API düzeyi 30) veya sonraki sürümlerdir.
  3. Asistan'ı ayarlamak ve çalıştığını doğrulamak için Ana Sayfa düğmesine uzun basın. Henüz yapmadıysanız cihazınızda Asistan'da oturum açmanız gerekir.

Android sanal cihazları hakkında daha fazla bilgi için Sanal cihaz oluşturma ve yönetme başlıklı makaleyi inceleyin.

Uygulamanın neler yapabileceğini görmek için kısa bir keşfe çıkın. Artı simgesine dokunarak yeni bir görev öğesi oluşturabilir, sağ üstteki menü öğelerini kullanarak da görev öğelerini tamamlanma durumuna göre arayabilir ve filtreleyebilirsiniz.

4. Kısayol deposu sınıfı oluşturma

Örnek uygulamamızdaki çeşitli sınıflar, dinamik kısayolları göndermek ve yönetmek için ShortcutManagerCompat API'sini çağırır. Kod fazlalığını azaltmak için, proje sınıflarınızın dinamik kısayolları kolayca yönetmesini sağlayacak bir depo uygulayacaksınız.

Depo tasarım kalıbı, kısayolları yönetmek için sorunsuz bir API sağlar. Deponun avantajı, temel API'nin ayrıntılarının minimum API'nin arkasında tek tip şekilde soyutlanmış olmasıdır. Aşağıdaki adımları uygulayarak depoyu uygulayın:

  1. ShortcutManagerCompat API'yi soyutlamak için ShortcutsRepository sınıfı oluşturun.
  2. Uygulamanın hizmet bulucusuna ShortcutsRepository yöntemleri ekleyin.
  3. ShortcutRepository hizmetini ana uygulamaya kaydedin.

Depoyu oluşturma

com.example.android.architecture.blueprints.todoapp.data.source paketinde ShortcutsRepository adlı yeni bir Kotlin sınıfı oluşturun. Bu paketi app/src/main/java klasöründe düzenlenmiş olarak bulabilirsiniz. Bu sınıfı, codelab kullanım alanımızı kapsayan minimum yöntemler kümesi sağlayan bir arayüzü uygulamak için kullanacaksınız.

ShortcutsRepository sınıfının konumunu gösteren Android Studio penceresi.

Şekil 2. Android Studio Proje Dosyaları penceresinde ShortcutsRepository sınıfının konumu gösteriliyor.

Aşağıdaki kodu yeni sınıfa yapıştırın:

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

Ardından, pushShortcut yöntemini ShortcutManagerCompat API'sini çağıracak şekilde güncelleyin. ShortcutsRepository sınıfını aşağıdaki kodla güncelleyin:

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

Önceki kod örneğinde API'ye appContext değerini ilettik. Bu, Application Context içeren bir sınıf özelliğidir. Bağlam, ana etkinlik yaşam döngüsünden daha uzun süre korunabileceğinden bellek sızıntılarını önlemek için Etkinlik Bağlamı yerine Uygulama Bağlamı kullanmak önemlidir.

Ayrıca API, Task nesnesi için bir ShortcutInfoCompat nesnesi iletmemizi gerektirir. Yukarıdaki kod örneğinde, createShortcutCompat özel yöntemini çağırarak bunu gerçekleştiriyoruz. Bu yöntemi, ShortcutInfoCompat nesnesi oluşturup döndürecek şekilde güncelleyeceğiz. Bunu yapmak için createShortcutCompat yer tutucusunu aşağıdaki kodla güncelleyin:

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

Bu sınıftaki kalan işlev sapları, dinamik kısayolları güncelleme ve silme işlemlerini ele alır. Aşağıdaki kodu kullanarak bu işlevleri etkinleştirin:

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

Hizmet bulucuya sınıf ekleme

ShortcutsRepository sınıfı oluşturulduktan sonraki adım, bu sınıfın örneklendirilmiş nesnelerini uygulamanın geri kalanında kullanılabilir hale getirmektir. Bu uygulama, hizmet bulucu kalıbını uygulayarak sınıf bağımlılıklarını yönetir. Android Studio'daki sınıf tarayıcıyı kullanarak hizmet bulucu sınıfını açın. Bunun için Navigate > Class'a (Gezin > Sınıf) gidin ve "ServiceLocator" yazın. IDE'nizde açmak için oluşturulan Kotlin dosyasını tıklayın.

ServiceLocator.kt'nın en üstünde, ShortcutsRepository ve SuppressLint paketlerini içe aktarmak için aşağıdaki kodu yapıştırın:

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

Aşağıdaki kodu ServiceLocator.kt gövdesine yapıştırarak ShortcutRepository hizmet üyelerini ve yöntemlerini ekleyin:

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

Kısayol hizmetini kaydetme

Son adım, yeni ShortcutsRepository hizmetinizi uygulamaya kaydetmektir. Android Studio'da TodoApplication.kt dosyasını açın ve aşağıdaki kodu dosyanın üst kısmına yakın bir yere kopyalayın:

TodoApplication.kt

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

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

Ardından, aşağıdaki kodu sınıfın gövdesine ekleyerek hizmeti kaydedin:

TodoApplication.kt

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

   //...

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

   //...
}

Uygulamayı oluşturun ve çalışmaya devam ettiğinden emin olun.

5. Yeni bir kısayol aktarma

Kısayol hizmetiniz oluşturulduğuna göre artık kısayolları göndermeye başlayabilirsiniz. Kullanıcılar bu uygulamada içerik (görev öğeleri) oluşturup daha sonra bu içeriklere geri dönebilmeyi beklediğinden, her yeni görev oluşturulduğunda GET_THING BII'ye bağlı dinamik bir kısayol göndererek bu içeriklere sesli erişim sağlayacağız. Bu sayede Asistan, kullanıcılar "Ok Google, SampleApp'te alışveriş listemi aç." gibi şeyler sorarak BII'yi tetiklediğinde onları doğrudan istedikleri görev öğesine yönlendirebilir.

Bu işlevi örnek uygulamada etkinleştirmek için aşağıdaki adımları tamamlayın:

  1. Görev listesi nesnelerini yönetmekten sorumlu olan ShortcutsRepository hizmetini AddEditTaskViewModel sınıfına aktarma.
  2. Kullanıcı yeni bir görev oluşturduğunda dinamik kısayol gönderme

Import ShortcutsRepository

Öncelikle ShortcutsRepository hizmetini AddEditTaskViewModel için kullanılabilir hale getirmemiz gerekir. Bunu yapmak için hizmeti ViewModelFactory sınıfına aktarın. Bu sınıf, AddEditTaskViewModel dahil olmak üzere ViewModel nesnelerini örneklendirmek için uygulamanın kullandığı fabrika sınıfıdır.

Android Studio'da Navigate > Class'a (Sınıf) gidip "ViewModelFactory" yazarak sınıf tarayıcısını açın. IDE'nizde açmak için oluşturulan Kotlin dosyasını tıklayın.

ViewModelFactory.kt'nın en üstünde, ShortcutsRepository ve SuppressLint paketlerini içe aktarmak için aşağıdaki kodu yapıştırın:

ViewModelFactory.kt

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

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

Ardından, ViewModelFactory gövdesini aşağıdaki kodla değiştirin:

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
}

Bir katman yukarı giderek ViewModelFactory değişikliklerini tamamlayın ve ShortcutsRepository değerini fabrikanın oluşturucusuna iletin. Navigate > File'a (Gezin > Dosya) gidip "FragmentExt.kt" yazarak Android Studio'nun dosya tarayıcısını açın. IDE'nizde açmak için util paketinde bulunan Kotlin dosyasını tıklayın.

FragmentExt.kt gövdesini aşağıdaki kodla değiştirin:

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

Kısayol gönderme

Örnek uygulamanın ShortcutsRepository sınıflarında kullanılabilen ViewModel soyutlama sınıfıyla, kullanıcı her yeni not oluşturduğunda dinamik bir kısayol göndermek için not oluşturmaktan sorumlu ViewModel sınıfı olan AddEditTaskViewModel sınıfını güncellersiniz.

Android Studio'da sınıf tarayıcısını açın ve "AddEditTaskViewModel" yazın. IDE'nizde açmak için oluşturulan Kotlin dosyasını tıklayın.

Öncelikle şu içe aktarma ifadesiyle bu sınıfa ShortcutsRepository paketini ekleyin:

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

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

Ardından, sınıf oluşturucuyu aşağıdaki kodla güncelleyerek shortcutsRepository sınıf özelliğini ekleyin:

AddEditTaskViewModel.kt

//...

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

    //...

ShortcutsRepository sınıfı eklendikten sonra bu sınıfı çağırmak için yeni bir işlev olan pushShortcut() oluşturun. Aşağıdaki özel işlevi AddEditTaskViewModel gövdesine yapıştırın:

AddEditTaskViewModel.kt

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

Son olarak, bir görev oluşturulduğunda yeni bir dinamik kısayol gönderin. saveTask() işlevinin içeriğini aşağıdaki kodla değiştirin:

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

Kodunuzu test etme

Sonunda kodumuzu test etmeye hazırız. Bu adımda, sesli komut özellikli bir dinamik kısayol gönderip Google Asistan uygulamasını kullanarak bu kısayolu incelersiniz.

Önizleme oluşturma

Google Asistan eklentisini kullanarak önizleme oluşturduğunuzda dinamik kısayollarınız test cihazınızdaki Asistan'da görünür.

Test eklentisini yükleyin

Google Asistan eklentiniz yoksa Android Studio'da şu adımları uygulayarak yükleyin:

  1. **Dosya > Ayarlar**'a (MacOS'te Android Studio > Tercihler) gidin.
  2. Eklentiler bölümünde Marketplace'e gidin ve "Google Asistan"ı arayın.
  3. Aracı yükleyin ve Android Studio'yu yeniden başlatın.

Önizlemeyi oluşturma

Android Studio'da aşağıdaki adımları uygulayarak önizleme oluşturun:

  1. Araçlar > Google Asistan > "Uygulama İşlemleri Test Aracı"nı tıklayın.
  2. Uygulama adı kutusunda "Yapılacaklar Listesi" gibi bir ad tanımlayın.
  3. Önizleme Oluştur'u tıklayın. İstenirse Uygulama İşlemleri politikalarını ve hizmet şartlarını inceleyip kabul edin.

Uygulama İşlemleri Test Aracı önizleme oluşturma bölmesi.

Şekil 3. Uygulama İşlemleri Test Aracı önizleme oluşturma bölmesi.

Test sırasında, Asistan'a gönderdiğiniz dinamik kısayollar, önizleme için sağladığınız Uygulama adına göre Asistan'da görünür.

Kısayolu itme ve inceleme

Örnek uygulamayı test cihazınızda yeniden başlatın ve aşağıdaki adımları uygulayın :

  1. "Start codelab" başlıklı yeni bir görev oluştur
  2. Google Asistan uygulamasını açıp "Kısayollarım" deyin veya yazın.
  3. Keşfet sekmesine dokunun. Örnek kısayolu görürsünüz.
  4. Kullanmak istediğiniz kısayola dokunun. Uygulama başlatıldığında filtre kutusunda kısayolun adı önceden doldurulmuş olarak gösterilir. Böylece, istenen görev öğesini kolayca bulabilirsiniz.

6. (İsteğe bağlı) Kısayolu güncelleme ve silme

Uygulamanız, çalışma zamanında yeni dinamik kısayollar göndermenin yanı sıra kullanıcı içeriğinizin ve tercihlerinizin mevcut durumunu yansıtacak şekilde bunları güncelleyebilir. Bir kullanıcı hedef öğeyi her değiştirdiğinde (ör. örnek uygulamamızda bir görevi yeniden adlandırdığında) mevcut kısayolları güncellemek iyi bir uygulamadır. Ayrıca, bozuk kısayolların kullanıcılara gösterilmesini önlemek için hedef kaynak her kaldırıldığında ilgili kısayolu da silmeniz gerekir.

Kısayolu güncelleme

Bir kullanıcı, görev öğesinin ayrıntılarını her değiştirdiğinde dinamik kısayolu güncellemek için AddEditTaskViewModel öğesini değiştirin. İlk olarak, sınıfın gövdesini aşağıdaki kodla güncelleyerek, depo sınıfımızı kullanan bir güncelleme işlevi ekleyin:

AddEditTaskViewModel.kt

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

Ardından, mevcut bir görev güncellendiğinde yeni yöntemimizi çağıracak şekilde saveTask() işlevini değiştirin.

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

Uygulamayı yeniden başlatıp aşağıdaki adımları uygulayarak kodunuzu test edin:

  1. Mevcut görev öğenizin başlığını "Finish codelab" (Codelab'i bitir) olarak yeniden adlandırın.
  2. "Ok Google, kısayollarım" diyerek Google Asistan'ı açın.
  3. Keşfet sekmesine dokunun. Test kısayolunuz için güncellenmiş bir kısa etiket görürsünüz.

Kısayolu kaldırma

Örnek uygulama kısayollarımız, kullanıcı bir görevi her sildiğinde kaldırılmalıdır. Örnek uygulamada, görev silme mantığı TaskDetailViewModel sınıfında bulunur. Bu sınıfı güncellemeden önce shortcutsRepository öğesini TaskDetailViewModel'ye aktarmak için ViewModelFactory uygulamasını tekrar güncellememiz gerekiyor.

ViewModelFactory dosyasını açın ve oluşturucu yönteminin içeriğini aşağıdaki kodla değiştirin:

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

Ardından TaskDetailViewModel uygulamasını açın. ShortcutsRepository modülünü içe aktarın ve aşağıdaki kodu kullanarak bunun için bir örnek değişkeni tanımlayın:

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

Son olarak, ilgili taskId kimlikli bir görev silindiğinde kimliğine göre kısayolu kaldırmak için shortcutsRepository işlevini çağıracak şekilde deleteTask() işlevini değiştirin:

TaskDetailViewModel.kt

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

Kodunuzu test etmek için uygulamayı yeniden başlatın ve aşağıdaki adımları uygulayın:

  1. Test görevinizi silin.
  2. Mevcut görev öğenizin başlığını "Finish codelab" (Codelab'i bitir) olarak yeniden adlandırın.
  3. "Ok Google, kısayollarım" diyerek Google Asistan'ı açın.
  4. Keşfet sekmesine dokunun. Test kısayolunuzun artık görünmediğini onaylayın.

7. Sonraki adımlar

Tebrikler! Sizin sayenizde örnek uygulamamızın kullanıcıları, Asistan'a "Ok Google, ExampleApp'te alışveriş listemi aç" gibi şeyler sorarak oluşturdukları notlara kolayca dönebiliyor. Kısayollar, kullanıcıların uygulamanızda sık kullanılan işlemleri tekrar etmesini kolaylaştırarak daha derin bir kullanıcı etkileşimi sağlar.

İşlediğimiz konular

Bu codelab'de şunları öğrendiniz:

  • Uygulamada dinamik kısayolları göndermeyle ilgili kullanım alanlarını belirleyin.
  • Depo, bağımlılık ekleme ve hizmet bulucu tasarım kalıplarını kullanarak kod karmaşıklığını azaltın.
  • Ses özellikli dinamik kısayolları, kullanıcı tarafından oluşturulan uygulama içeriğine yönlendirin.
  • Mevcut kısayolları güncelleme ve kaldırma

Sırada ne var?

Buradan, Görev Listesi uygulamanızda daha fazla iyileştirme yapmayı deneyebilirsiniz. Tamamlanmış projeye referans vermek için GitHub'daki –codelab-complete branch deposuna bakın.

Bu uygulamayı Uygulama İşlemleri ile genişletme hakkında daha fazla bilgi edinmek için aşağıdaki önerilerden yararlanabilirsiniz:

Actions on Google yolculuğunuza devam etmek için aşağıdaki kaynakları inceleyin:

En son duyurularımızdan haberdar olmak için Twitter'da @ActionsOnGoogle hesabını takip edin ve geliştirdiklerinizi paylaşmak için #appActions etiketini kullanarak tweet atın.

Geri bildirim anketi

Son olarak, bu codelab ile ilgili deneyiminizi paylaşmak için lütfen bu anketi doldurun.