1. نظرة عامة
في الدرس التطبيقي السابق حول الترميز، استخدمت اختصارات ثابتة لتنفيذ أهداف مضمَّنة (BII) شائعة الاستخدام في نموذج تطبيق. يستخدم مطوّرو تطبيقات Android خدمة "مهامّ في التطبيقات" لتوسيع نطاق وظائف التطبيقات لتشمل "مساعد Google".
يتم تجميع الاختصارات الثابتة مع تطبيق ولا يمكن تحديثها إلا من خلال طرح إصدارات جديدة من التطبيق. يتم تفعيل الوظائف الصوتية للعناصر الديناميكية في أحد التطبيقات، مثل المحتوى الذي ينشئه المستخدمون، باستخدام الاختصارات الديناميكية. تدفع التطبيقات اختصارات ديناميكية بعد أن ينفذ المستخدمون إجراءات ذات صلة، مثل إنشاء ملاحظة جديدة في تطبيق تتبع المهام. يتيح لك تطبيق "مهامّ في التطبيقات" تفعيل هذه الاختصارات الصوتية من خلال ربطها بالأداة BII، ما يتيح للمستخدمين الوصول إلى المحتوى الخاص بهم من خلال "مساعد Google" بقول عبارات مثل "Ok Google، أريد فتح قائمة البقالة على ExampleApp".
الشكل 1. ثلاث شاشات تقدّمية تعرض مهمة أنشأها المستخدم، بينما يطلق "مساعد Google" اختصارًا ديناميكيًا إلى عنصر المهمة هذا.
ما الذي ستقوم ببنائه
في هذا الدرس التطبيقي حول الترميز، سيتم تفعيل الاختصارات الديناميكية للصوت في نموذج قائمة مهام على Android، ما يتيح للمستخدمين توجيه طلب إلى "مساعد Google" لفتح عناصر قائمة المهام التي ينشئونها في التطبيق. ويمكنك تحقيق ذلك باستخدام أنماط بنية Android، وتحديدًا أنماط المستودع ومحدِّد موقع الخدمة وViewModel.
المتطلبات الأساسية
يستند هذا الدرس التطبيقي إلى مفاهيم "مهامّ في التطبيقات" التي تم تناولها في الدرس التطبيقي السابق حول الترميز، وخاصةً معرّفات BII والاختصارات الثابتة. إذا كنت مستخدمًا جديدًا لخدمة "مهامّ في التطبيقات"، ننصحك بإكمال هذا الدرس التطبيقي قبل المتابعة.
بالإضافة إلى ذلك، يُرجى التأكّد من ضبط الإعدادات التالية في بيئة التطوير قبل المتابعة:
- وحدة طرفية لتشغيل أوامر واجهة الأوامر مع تثبيت git
- يشير إلى أحدث إصدار ثابت من استوديو Android.
- جهاز Android فعلي أو افتراضي مزود بإمكانية الاتصال بالإنترنت.
- حساب Google تم تسجيل الدخول منه إلى "استوديو Android" وتطبيق Google وتطبيق "مساعد Google"
2. التعرّف على طريقة العمل
يتضمن تمكين اختصار ديناميكي للوصول الصوتي باستخدام الخطوات التالية:
- ربط اختصار ديناميكي بـ BII مؤهل
- تفعيل "مساعد Google" من نقل الاختصارات من خلال إضافة مكتبة دمج "اختصارات Google"
- الدفع اختصارًا عندما يُكمل المستخدم المهمة ذات الصلة داخل التطبيق
اختصارات الربط
لإتاحة الوصول إلى الاختصار الديناميكي من "مساعد Google"، يجب ربطه بخدمة BII ذات الصلة. عند تشغيل دالة BII مع اختصار، يطابق "مساعد Google" المَعلمات في طلب المستخدم مع الكلمات الرئيسية المحدَّدة في الاختصار المرتبط. على سبيل المثال:
- يمكن أن يسمح الاختصار المرتبط بالرمز
GET_THING
BII للمستخدمين بطلب محتوى معيّن داخل التطبيق من "مساعد Google" مباشرةً. * "Ok Google، أريد فتح قائمة البقالة على ExampleApp". - قد يسمح الاختصار المرتبط بالوحدة
ORDER_MENU_ITEM
BII للمستخدمين بإعادة تشغيل الطلبات السابقة. * "Ok Google، أريد طلب خدماتي المعتادة من ExampleApp".
يمكنك الرجوع إلى مرجع الأغراض المضمَّنة للحصول على قائمة كاملة مصنَّفة بمعرّفات BII.
تقديم اختصارات لخدمة "مساعد Google"
بعد ربط اختصاراتك بـ BII، ستتمثل الخطوة التالية في تفعيل "مساعد Google" من نقل هذه الاختصارات من خلال إضافة مكتبة تكامل اختصارات Google إلى مشروعك. عند استخدام هذه المكتبة، سيطّلع "مساعد Google" على كل اختصار يطرحه تطبيقك، ما يتيح للمستخدمين تشغيل هذه الاختصارات من خلال استخدام عبارة تشغيل الاختصار في "مساعد Google".
3- إعداد بيئة التطوير
يستخدم هذا الدرس التطبيقي حول الترميز نموذجًا لتطبيق قائمة مهام مصمّمًا لنظام التشغيل Android. باستخدام هذا التطبيق، يمكن للمستخدمين إضافة عناصر إلى القوائم والبحث عن عناصر قائمة المهام حسب الفئة وفلترة المهام حسب حالة الإكمال. يمكنك تنزيل نموذج التطبيق وإعداده من خلال إكمال هذا القسم.
تنزيل ملفاتك الأساسية
شغّل الأمر التالي لاستنساخ نموذج مستودع GitHub للتطبيق:
git clone https://github.com/actions-on-google/app-actions-dynamic-shortcuts.git
بعد استنساخ المستودع، اتّبِع الخطوات التالية لفتحه في "استوديو Android":
- في مربّع الحوار مرحبًا بك في "استوديو Android"، انقر على استيراد مشروع.
- اختَر المجلد الذي استنسخت المستودع فيه.
وبدلاً من ذلك، يمكنك عرض إصدار من نموذج التطبيق الذي يمثّل الدرس التطبيقي المكتمل حول الترميز من خلال استنساخ فرع codelab-complete
من مستودع جيت هب الخاص به:
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
إلى معلومات فريدة لك.
إضافة تبعيات واجهة برمجة التطبيقات للاختصارات
أضِف مكتبات 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'
...
}
اختبار التطبيق على جهازك
قبل إجراء المزيد من التغييرات على التطبيق، من المفيد الحصول على فكرة عما يمكن أن يفعله نموذج التطبيق. لتشغيل التطبيق على المحاكي، يمكنك اتباع الخطوات التالية:
- في "استوديو Android"، اختَر "تشغيل" > شغِّل التطبيق أو انقر على تشغيل في شريط الأدوات.
- في مربّع الحوار اختيار هدف النشر، اختَر جهازًا وانقر على حسنًا. إصدار نظام التشغيل المقترَح هو Android 10 (المستوى 30 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، على الرغم من أنّ ميزة "مهامّ في التطبيقات" تعمل على الأجهزة حتى Android 5 (المستوى 21 من واجهة برمجة التطبيقات).
- اضغط مع الاستمرار على زر الشاشة الرئيسية لإعداد "مساعد Google" والتأكّد من أنّه يعمل. عليك تسجيل الدخول إلى "مساعد Google" على جهازك، إذا لم يسبق لك إجراء ذلك.
لمزيد من المعلومات حول أجهزة Android الافتراضية، يُرجى الاطّلاع على مقالة إنشاء الأجهزة الافتراضية وإدارتها.
استكشف التطبيق بإيجاز لمعرفة ما يمكنه فعله. يؤدي النقر على أيقونة علامة الجمع إلى إنشاء عنصر مهمة جديد، وتسمح لك عناصر القائمة في أعلى اليسار بالبحث عن عناصر المهام وتصفيتها حسب حالة الإكمال.
4. إنشاء فئة لمستودع الاختصارات
ستطلب العديد من الصفوف في نموذج التطبيق الخاص بنا واجهة برمجة التطبيقات ShortcutManagerCompat
لإرسال الاختصارات الديناميكية وإدارتها. لتقليل تكرار التعليمات البرمجية، ستقوم بتنفيذ مستودع لتمكين فئات مشروعك من إدارة الاختصارات الديناميكية بسهولة.
يوفر نمط تصميم المستودع واجهة برمجة تطبيقات نظيفة لإدارة الاختصارات. تتمثل ميزة أي مستودع في استخلاص تفاصيل واجهة برمجة التطبيقات الأساسية بشكل موحّد خلف واجهة برمجة تطبيقات مبسّطة. أنشئ المستودع باتباع الخطوات التالية:
- أنشِئ فئة
ShortcutsRepository
لاستخراج بياناتShortcutManagerCompat
API. - إضافة طرق
ShortcutsRepository
إلى محدِّد مواقع الخدمات في التطبيق - تسجيل خدمة
ShortcutRepository
في التطبيق الرئيسي
إنشاء المستودع
أنشِئ فئة Kotlin جديدة باسم ShortcutsRepository
في حزمة com.example.android.architecture.blueprints.todoapp.data.source
. يمكنك العثور على هذه الحزمة منظمة في المجلد app/src/main/java
. ستستخدم هذه الفئة لتنفيذ واجهة توفّر مجموعة محدودة من الطرق التي تغطي حالة استخدام الدرس التطبيقي حول الترميز.
الشكل 2. نافذة "ملفات المشاريع" في "استوديو Android" تعرض موقع الفئة 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>) {
//...
}
}
بعد ذلك، عليك تعديل الطريقة pushShortcut
لطلب بيانات من ShortcutManagerCompat
API. عدِّل الفئة 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
إلى واجهة برمجة التطبيقات. هذا موقع إلكتروني للفئة يتضمّن سياق التطبيق. من المهم استخدام سياق التطبيق (بدلاً من سياق النشاط) لتجنُّب تسرُّب الذاكرة، نظرًا لأنه قد يتم الاحتفاظ بالسياق لفترة أطول من دورة حياة نشاط المضيف.
بالإضافة إلى ذلك، تتطلّب واجهة برمجة التطبيقات أن نمرر كائن ShortcutInfoCompat
لكائن "Task". في نموذج الرمز السابق، يتم تنفيذ ذلك من خلال استدعاء الطريقة الخاصة createShortcutCompat
، والتي سنعدّلها لإنشاء عنصر ShortcutInfoCompat
وإرجاعه. لتنفيذ هذا الإجراء، يجب تعديل الخلاصة 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()
}
تتعامل الأجزاء المتبقية من الدوال في هذا الصف مع تحديث الاختصارات الديناميكية وحذفها. قم بتمكين هذه الدوال عن طريق تحديثها بالتعليمة البرمجية التالية:
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
، تتمثل الخطوة التالية في إتاحة العناصر التي تم إنشاء نسخة مثيل لها في هذه الفئة لبقية التطبيق. يدير هذا التطبيق تبعيات الفئة من خلال تنفيذ نمط أداة البحث عن أماكن الخدمة. افتح فئة محدّد موقع الخدمة باستخدام متصفّح الفئات في "استوديو Android" من خلال الانتقال إلى التنقّل > Class واكتب "ServiceLocator". انقر على ملف Kotlin الناتج لفتحه في بيئة التطوير المتكاملة (IDE).
في أعلى 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"، افتح 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- دفع اختصار جديد
بعد إنشاء خدمة الاختصارات، ستكون جاهزًا لبدء إرسال الاختصارات. بما أنّ المستخدمين يُنشئون محتوى (عناصر المهام) في هذا التطبيق ويتوقّعون أن يتمكّنوا من الرجوع إليها لاحقًا، سنفعّل الوصول الصوتي إلى هذا المحتوى من خلال إرسال اختصار ديناميكي يرتبط بـ GET_THING
BII في كل مرة ينشئ فيها المستخدم مهمة جديدة. يتيح ذلك لخدمة "مساعد Google" توجيه المستخدمين مباشرةً إلى عنصر المَهمّة المطلوب عند تشغيل BII، وذلك من خلال توجيه طلبات مثل "Ok Google، أريد فتح قائمة البقالة على SampleApp".
يمكنك تفعيل هذه الوظيفة في نموذج التطبيق من خلال إكمال الخطوات التالية:
- جارٍ استيراد خدمة
ShortcutsRepository
إلى الفئةAddEditTaskViewModel
، المسؤولة عن إدارة عناصر قائمة المهام. - دفع اختصار ديناميكي عندما ينشئ المستخدم مهمة جديدة
استيراد مستودع الاختصارات
نحتاج أولاً إلى إتاحة خدمة "ShortcutsRepository
" لـ "AddEditTaskViewModel
". لتحقيق ذلك، عليك استيراد الخدمة إلى ViewModelFactory
، وهي فئة المصنع التي يستخدمها التطبيق لإنشاء مثيل لكائنات ViewModel، بما في ذلك AddEditTaskViewModel
.
افتح متصفّح الصف في "استوديو Android" من خلال الانتقال إلى التنقّل > Class واكتب "ViewModelfactor" إلى البيانات". انقر على ملف Kotlin الناتج لفتحه في بيئة التطوير المتكاملة (IDE).
في أعلى 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
إلى الدالة الإنشائية للمصنع. افتح متصفح الملفات في "استوديو Android" من خلال الانتقال إلى التنقّل > ملف وكتابة "FragmentExt.kt". انقر على ملف Kotlin الناتج في الحزمة util لفتحه في بيئة التطوير المتكاملة (IDE).
استبدل نص 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"، افتح متصفّح الصف واكتب "AddEditTaskViewModel". انقر على ملف Kotlin الناتج لفتحه في بيئة التطوير المتكاملة (IDE).
أولاً، يجب إضافة حزمة ShortcutsRepository
إلى هذه الفئة باستخدام عبارة الاستيراد التالية:
package com.example.android.architecture.blueprints.todoapp.addedittask
//Other import statements
import com.example.android.architecture.blueprints.todoapp.data.source.ShortcutsRepository
بعد ذلك، أضِف السمة الخاصة بالفئة shortcutsRepository
من خلال تعديل الدالة الإنشائية للفئة باستخدام الرمز التالي:
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".
إنشاء معاينة
يتيح إنشاء معاينة باستخدام مكوّن "مساعد Google" الإضافي ظهور الاختصارات الديناميكية في "مساعد Google" على جهاز الاختبار.
تثبيت المكوّن الإضافي للاختبار
إذا لم يكن لديك مكوّن "مساعد Google" الإضافي، يمكنك تثبيته باتّباع الخطوات التالية في "استوديو Android":
- انتقِل إلى **ملف >. الإعدادات (استوديو Android > الإعدادات المفضّلة على نظام التشغيل MacOS).
- في قسم Plugins (المكوّنات الإضافية)، انتقِل إلى Marketplace وابحث عن "مساعد Google".
- إذا لم تتمكن من العثور على المكوّن الإضافي على Marketplace، يمكنك تنزيل المكوّن الإضافي يدويًا واتّباع التعليمات الواردة في تثبيت المكون الإضافي من القرص.
- ثبِّت الأداة وأعِد تشغيل "استوديو Android".
إنشاء المعاينة
يمكنك إنشاء معاينة باتّباع الخطوات التالية في "استوديو Android":
- انقر على الأدوات >. مساعد Google > "أداة اختبار إجراءات التطبيقات".
- في المربّع اسم التطبيق، حدِّد اسمًا مثل "قائمة المهام".
- انقر على إنشاء معاينة. راجِع سياسات خدمة "مهامّ في التطبيقات" وبنود الخدمة واقبلها إذا طُلِب منك ذلك.
الشكل 3. جزء إنشاء معاينة أداة اختبار "إجراءات التطبيقات"
أثناء الاختبار، ستظهر الاختصارات الديناميكية التي ترسلها إلى "مساعد Google" في "مساعد Google" وتكون منظّمة حسب اسم التطبيق الذي قدّمته للمعاينة.
إرسال اختصار وفحصه
أعِد تشغيل نموذج التطبيق على جهازك الاختباري ونفِّذ الخطوات التالية :
- إنشاء مهمة جديدة بعنوان "بدء الدرس التطبيقي حول الترميز"
- افتح تطبيق "مساعد Google" وقُل "اختصاراتي" أو اكتبها.
- انقر على علامة التبويب استكشاف. من المفترض أن يظهر لك اختصار النموذج.
- انقر على الاختصار لاستدعاءه. من المفترض أن يظهر لك تشغيل التطبيق باسم الاختصار تمت تعبئته تلقائيًا في مربّع الفلتر، ما يسهِّل العثور على عنصر المهمة المطلوب.
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)
}
}
اختبِر الرمز من خلال إعادة تشغيل التطبيق واتّباع الخطوات التالية:
- أعِد تسمية عنوان عنصر المهمة الحالي ليصبح "إنهاء الدرس التطبيقي حول الترميز".
- يمكنك فتح "مساعد Google" من خلال قول "Ok Google، اختصاراتي".
- انقر على علامة التبويب استكشاف. من المفترض أن يظهر لك تصنيف قصير معدَّل لاختصار الاختبار.
إزالة اختصار
يجب إزالة نماذج اختصارات التطبيقات عندما يحذف أحد المستخدمين مهمة. في نموذج التطبيق، يتوفّر منطق حذف المهام في صف واحد (TaskDetailViewModel
). قبل تحديث هذا الصف، يجب تحديث ViewModelFactory
مرة أخرى لتمرير shortcutsRepository
إلى TaskDetailViewModel
.
افتح ViewModelFactory
واستبدِل محتوى طريقة الدالة الإنشائية بالتعليمة البرمجية التالية:
//...
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))
}
}
لاختبار الرمز، يُرجى إعادة تشغيل التطبيق واتّباع الخطوات التالية:
- احذف مهمة الاختبار.
- أعِد تسمية عنوان عنصر المهمة الحالي ليصبح "إنهاء الدرس التطبيقي حول الترميز".
- يمكنك فتح "مساعد Google" من خلال قول "Ok Google، اختصاراتي".
- انقر على علامة التبويب استكشاف. تأكَّد من أنّ اختصار الاختبار لم يعُد يظهر.
7. الخطوات التالية
تهانينا! بفضل مساعدتك، يمكن لمستخدمي نموذج التطبيق العودة بسهولة إلى الملاحظات التي ينشئونها، وذلك من خلال توجيه طلب إلى "مساعد Google" مثلاً، "Ok Google، أريد فتح قائمة البقالة على ExampleApp". تشجّع الاختصارات على تعزيز تفاعل المستخدمين من خلال تسهيل إعادة تشغيل الإجراءات الأكثر استخدامًا في تطبيقك.
النقاط التي تناولناها
في هذا الدرس التطبيقي حول الترميز، تعلمتَ كيفية:
- يمكنك تحديد حالات استخدام إرسال الاختصارات الديناميكية في أحد التطبيقات.
- يمكنك تقليل تعقيد الرمز باستخدام أنماط تصميم مستودع وإدخال التبعية ومحدد موقع الخدمة.
- إدخال الاختصارات الديناميكية المستندة إلى الصوت للوصول إلى محتوى التطبيق من إنشاء المستخدمين
- تعديل الاختصارات الحالية وإزالتها
الخطوات التالية
من هنا، يمكنك محاولة إجراء مزيد من التحسينات على تطبيق "قائمة المهام". للرجوع إلى المشروع النهائي، يُرجى الاطّلاع على -فرع repo-complete-متوافق مع الترميز على GitHub.
في ما يلي بعض الاقتراحات لمزيد من المعلومات حول توسيع نطاق هذا التطبيق باستخدام ميزة "مهامّ في التطبيقات":
- يمكنك الاطّلاع على نموذج قائمة المهام باستخدام "إحصاءات Google لبرنامج Firebase" للتعرّف على كيفية تتبُّع أداء "مهامّ في التطبيقات".
- انتقِل إلى مرجع الأهداف المضمّنة في "مهامّ في التطبيقات" للاطّلاع على مزيد من الطرق لتوسيع نطاق وصول تطبيقاتك إلى "مساعد Google".
لمواصلة رحلتك في "المهام مع مساعد Google"، يُرجى الاطّلاع على المراجع التالية:
- actions.google.com: الموقع الإلكتروني الرسمي للمستندات المتعلقة بـ "المهام مع مساعد Google".
- نموذج فهرس "المهام في التطبيقات": نموذج تطبيقات ورموز لاستكشاف إمكانات "مهامّ في التطبيقات".
- مستودع "المهام مع مساعد Google" على GitHub: نموذج الرموز البرمجية والمكتبات.
- r/GoogleAssistantDev: منتدى Reddit الرسمي للمطوّرين الذين يستخدمون "مساعد Google"
يمكنك متابعتنا على Twitter @ActionsOnGoogle لمعرفة أحدث الإشعارات، كما يمكنك نشر تغريدة على #appActions لمشاركة ما أنجزته.
استطلاع لجمع الملاحظات
أخيرًا، يُرجى ملء هذا الاستطلاع لتقديم ملاحظاتك حول تجربتك في هذا الدرس التطبيقي حول الترميز.