1. نظرة عامة
في الدرس التطبيقي السابق حول الترميز، استخدمت اختصارات ثابتة لتنفيذ أهداف مضمَّنة (BII) شائعة الاستخدام في نموذج تطبيق. يستخدم مطوّرو تطبيقات Android خدمة "مهامّ في التطبيقات" لتوسيع نطاق وظائف التطبيقات لتشمل "مساعد Google".
يتم تجميع الاختصارات الثابتة مع تطبيق ولا يمكن تحديثها إلا من خلال طرح إصدارات جديدة من التطبيق. يتم تفعيل الوظائف الصوتية للعناصر الديناميكية في أحد التطبيقات، مثل المحتوى الذي ينشئه المستخدمون، باستخدام الاختصارات الديناميكية. تُرسِل التطبيقات اختصارات ديناميكية بعد أن ينفّذ المستخدمون إجراءات ذات صلة، مثل إنشاء ملاحظة جديدة في تطبيق تتبُّع المهام. باستخدام "إجراءات التطبيقات"، يمكنك تفعيل هذه الاختصارات للصوت من خلال ربطها بواجهة برمجة تطبيقات تفاعلية، ما يتيح للمستخدمين الوصول إلى المحتوى الخاص بهم من خلال "مساعد Google" من خلال قول عبارات مثل "مرحبًا Google، افتح قائمة البقالة على ExampleApp".
الشكل 1: ثلاث شاشات تقدّمية تعرض مهمة أنشأها المستخدم، بينما يطلق "مساعد Google" اختصارًا ديناميكيًا إلى عنصر المهمة هذا.
ما ستُنشئه
في هذا الدرس التطبيقي حول الترميز، سيتم تفعيل الاختصارات الديناميكية للصوت في نموذج قائمة مهام على Android، ما يتيح للمستخدمين توجيه طلب إلى "مساعد Google" لفتح عناصر قائمة المهام التي ينشئونها في التطبيق. ويمكنك تحقيق ذلك باستخدام أنماط بنية Android، وتحديدًا أنماط المستودع ومحدِّد موقع الخدمة وViewModel.
المتطلبات الأساسية
يستند هذا الدرس التطبيقي حول الترميز إلى مفاهيم "مهامّ في التطبيقات" التي تم تناولها في الدرس التطبيقي السابق حول الترميز، وخاصةً معرّفات BII والاختصارات الثابتة. إذا كنت مستخدمًا جديدًا لخدمة "مهامّ في التطبيقات"، ننصحك بإكمال هذا الدرس التطبيقي قبل المتابعة.
بالإضافة إلى ذلك، تأكَّد من أنّ بيئة التطوير تتضمّن الإعدادات التالية قبل المتابعة:
- وحدة طرفية لتشغيل أوامر واجهة الأوامر مع تثبيت git
- يشير إلى أحدث إصدار ثابت من استوديو Android.
- جهاز Android فعلي أو افتراضي مزود بإمكانية الاتصال بالإنترنت.
- حساب Google تم تسجيل الدخول منه إلى "استوديو Android" وتطبيق Google وتطبيق "مساعد Google"
2. فهم آلية العمل
تتضمّن خطوات تفعيل اختصار ديناميكي لتطبيق Voice Access ما يلي:
- ربط اختصار ديناميكي بـ BII مؤهل
- تفعيل "مساعد Google" لمعالجة الاختصارات من خلال إضافة مكتبة دمج اختصارات Google
- الدفع اختصارًا عندما يُكمل المستخدم المهمة ذات الصلة داخل التطبيق
اختصارات الربط
لإتاحة الوصول إلى الاختصار الديناميكي من "مساعد Google"، يجب ربطه بخدمة BII ذات الصلة. عند تشغيل دالة BII مع اختصار، يطابق "مساعد Google" المَعلمات في طلب المستخدم مع الكلمات الرئيسية المحدَّدة في الاختصار المرتبط. على سبيل المثال:
- يمكن أن يسمح الاختصار المرتبط بالمفتاح
GET_THING
BII للمستخدمين بطلب محتوى معيّن داخل التطبيق من "مساعد Google" مباشرةً. * "Ok Google، أريد فتح قائمة البقالة على ExampleApp". - يمكن أن يسمح اختصار مرتبط بوحدة التحكّم في الأجهزة البدنية
START_EXERCISE
للمستخدمين بالاطّلاع على جلسات التمارين الرياضية. * "Ok Google، أريد أن أطلب من ExampleApp بدء تمريناتي المعتادة".
راجِع مرجع الأهداف المضمّنة للحصول على قائمة كاملة مصنّفة بالأهداف المضمّنة.
توفير اختصارات إلى "مساعد 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
من مستودع 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
إلى معلومات فريدة لك.
إضافة تبعيات واجهة برمجة التطبيقات للاختصارات
أضِف مكتبات 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
. - أضِف طرقًا
ShortcutsRepository
إلى محدِّد الخدمات في التطبيق. - سجِّل خدمة
ShortcutRepository
في التطبيق الرئيسي.
إنشاء المستودع
أنشئ فئة Kotlin جديدة باسم ShortcutsRepository
في حزمة com.example.android.architecture.blueprints.todoapp.data.source
. يمكنك العثور على هذه الحزمة منظَّمة في مجلد app/src/main/java
. ستستخدم هذه الفئة لتنفيذ واجهة تقدّم مجموعة أساسية من الطرق التي تغطي حالة استخدام الدرس التطبيقي حول الترميز.
الشكل 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>) {
//...
}
}
بعد ذلك، عليك تعديل الطريقة 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" من خلال الانتقال إلى التنقّل > الفئة وكتابة 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 توجيه المستخدمين مباشرةً إلى عنصر المهمة المطلوب عند بدء تفاعل IB عن طريق طرح أسئلة مثل "مرحبًا Google، أريد فتح قائمة البقالة على SampleApp".
يمكنك تفعيل هذه الوظيفة في التطبيق التجريبي من خلال إكمال الخطوات التالية:
- استيراد خدمة
ShortcutsRepository
إلى فئةAddEditTaskViewModel
المسؤولة عن إدارة عناصر قائمة المهام - إرسال اختصار ديناميكي عندما ينشئ المستخدم مهمة جديدة
استيراد ShortcutsRepository
علينا أولاً إتاحة خدمة 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).
- في قسم المكوّنات الإضافية، انتقِل إلى Marketplace (السوق) وابحث عن "مساعد Google".
- إذا لم تتمكّن من العثور على المكوّن الإضافي في Marketplace، يمكنك تنزيل المكوّن الإضافي يدويًا واتّباع تعليمات تثبيت المكوّن الإضافي من القرص.
- ثبِّت الأداة وأعِد تشغيل "استوديو Android".
إنشاء المعاينة
يمكنك إنشاء معاينة باتّباع الخطوات التالية في Android Studio:
- انقر على الأدوات > مساعد 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". تشجّع الاختصارات على تعزيز تفاعل المستخدمين من خلال تسهيل إعادة تشغيل الإجراءات الأكثر استخدامًا في تطبيقك.
النقاط التي تناولناها
في هذا الدرس التطبيقي حول الترميز، تعلمتَ كيفية:
- حدِّد حالات الاستخدام لعرض اختصارات ديناميكية في أحد التطبيقات.
- يمكنك تقليل تعقيد الرمز باستخدام أنماط تصميم مستودع وإدخال التبعية ومحدد موقع الخدمة.
- إدخال الاختصارات الديناميكية المستندة إلى الصوت للوصول إلى محتوى التطبيق من إنشاء المستخدمين
- تعديل الاختصارات الحالية وإزالتها
الخطوات التالية
من هنا، يمكنك محاولة إجراء مزيد من التحسينات على تطبيق "قائمة المهام". للرجوع إلى المشروع النهائي، يُرجى الاطّلاع على -الفرع الكامل للدرس التطبيقي حول الترميز على GitHub.
في ما يلي بعض الاقتراحات لمزيد من المعلومات حول توسيع نطاق هذا التطبيق باستخدام ميزة "مهامّ في التطبيقات":
- يمكنك الاطّلاع على نموذج قائمة المهام باستخدام "إحصاءات Google لبرنامج Firebase" للتعرّف على كيفية تتبُّع أداء "مهامّ في التطبيقات".
- يمكنك الانتقال إلى مرجع الأهداف المضمّنة في "إجراءات التطبيقات" للتعرّف على المزيد من الطرق لتوسيع نطاق تطبيقاتك لتتضمّن "مساعد Google".
لمواصلة رحلتك في "المهام مع مساعد Google"، يُرجى الاطّلاع على المراجع التالية:
- actions.google.com: الموقع الإلكتروني الرسمي للمستندات المتعلّقة بميزة "المهام مع مساعد Google"
- فهرس نماذج "إجراءات التطبيقات": نماذج للتطبيقات والرموز البرمجية لاستكشاف إمكانات "إجراءات التطبيقات"
- مستودع "المهام مع مساعد Google" على GitHub: نموذج الرموز البرمجية والمكتبات.
- r/GoogleAssistantDev: منتدى Reddit الرسمي للمطوّرين الذين يعملون مع "مساعد Google"
يمكنك متابعتنا على Twitter @ActionsOnGoogle لمعرفة أحدث الإشعارات، كما يمكنك نشر تغريدة على #appActions لمشاركة ما أنجزته.
استطلاع لجمع الملاحظات
أخيرًا، يُرجى ملء هذا الاستطلاع لتقديم ملاحظاتك حول تجربتك في هذا الدرس التطبيقي حول الترميز.