غالبًا ما تُستخدم أجهزة Wear OS لتجارب طويلة الأمد، مثل تتبُّع التمارين الرياضية. قد تقدّم هذه التجارب أيضًا معلومات مهمة تهمّ المستخدم ويحتاج إلى الوصول إليها بسرعة.
وهذا يطرح تحديًا في تجربة المستخدم، فإذا بدأ المستخدم مهمة ثم انتقل إلى خلفية شاشة الساعة، يجب أن يظل بإمكانه تنفيذ كل مما يلي:
- مواصلة تلقّي الإشعارات المهمة
- يمكنك الرجوع إلى المهمة بنقرة واحدة.
قد يكون من الصعب العودة إلى التطبيق باستخدام مشغّل التطبيقات، خاصةً أثناء التنقّل، ما يؤدي إلى حدوث مشاكل غير ضرورية.
اعتبارًا من Wear OS 7، الحلّ هو إقران إشعار بنشاط مستمر في الخلفية بإشعار OngoingActivity أو تحديث فوري. يتيح ذلك للجهاز عرض معلومات حول النشاط الذي يستغرق وقتًا طويلاً في جميع أنحاء واجهة المستخدم، ما يتيح ميزات مثل الرمز القابل للنقر في أسفل خلفية شاشة الساعة. يُبقي هذا المؤشر المستخدمين على دراية بالمهمة التي يتم تنفيذها في الخلفية، كما يوفّر طريقة بنقرة واحدة للعودة إلى التطبيق.
يؤدي النشاط المستمر في الخلفية أو التحديث الفوري أيضًا إلى إبقاء تطبيقك مرئيًا لفترة أطول، ما يمنع النظام من الرجوع إلى خلفية شاشة الساعة بعد فترة من عدم النشاط. لمزيد من المعلومات، يُرجى الاطّلاع على إبقاء تطبيقك مرئيًا على Wear.
استخدِم إشعارًا بنشاط مستمر في الخلفية أو تحديثات فورية للتجارب التي من المحتمل أن تستغرق أكثر من دقيقة واحدة، أو في الحالات التي من المحتمل أن يغادر فيها المستخدم تطبيقك قبل اكتمال المهمة.
الاستخدامات المناسبة: التمارين الرياضية التي يتم تتبُّعها والمؤقتات وتتبُّع مشاركة الرحلة والتسجيلات الصوتية الطويلة، مثل اجتماع وقوائم التسوّق التي يجب أن تكون متاحة أثناء وجود المستخدم في المتجر
الاستخدامات غير المناسبة: تسجيل رسائل صوتية قصيرة، والعروض الترويجية، وحالة تطبيق يتم تحديثه، وأحداث التقويم القادمة
ملاحظة مهمة: يُعد استخدام
OngoingActivityأو التحديث المباشر في هذه السيناريوهات شرطًا بموجب إرشادات جودة تطبيقات Wear OS WO-V4.
على سبيل المثال، في تطبيق التمارين الرياضية هذا، يمكن أن تظهر المعلومات على خلفية ساعة المستخدم كرمز قابل للنقر عليه:
الشكل 1: مؤشر النشاط
يعرض إشعار بنشاط مستمر في الخلفية أيضًا معلومات في قسم التطبيقات المستخدَمة مؤخرًا ضمن مشغّل التطبيقات العام. ويوفّر ذلك مكانًا آخر مناسبًا للمستخدمين للاطّلاع على حالة مهمتهم وإعادة التفاعل مع التطبيق:
الشكل 2: مشغّل التطبيقات العالمي
في ما يلي بعض الحالات التي يكون فيها استخدام إشعار بنشاط مستمر في الخلفية مرتبط بـ "نشاط مستمر في الخلفية" مناسبًا:
الشكل 3: الموقّت: يتم احتساب الوقت بشكل نشط ويتم إيقافه مؤقتًا أو إيقافه نهائيًا.
الشكل 4. التنقّل خطوة بخطوة: تعلن هذه الميزة عن الاتّجاهات المؤدية إلى وجهة معيّنة. تنتهي عندما يصل المستخدم إلى الوجهة أو يتوقف عن التنقّل.
الشكل 5. الوسائط: تشغيل الموسيقى طوال الجلسة تنتهي الجلسة فورًا بعد أن يوقفها المستخدم مؤقتًا.
تنشئ Wear "الأنشطة الجارية" تلقائيًا لتطبيقات الوسائط.
يمكنك الاطّلاع على درس تطبيقي حول الترميز بشأن ميزة "النشاط الجاري" للحصول على مثال مفصّل حول كيفية إنشاء أنشطة جارية لأنواع أخرى من التطبيقات.
الإعداد
لبدء استخدام واجهة برمجة التطبيقات Ongoing Activity API في تطبيقك، أضِف التبعيات التالية إلى ملف build.gradle في تطبيقك:
dependencies {
implementation "androidx.wear:wear-ongoing:1.1.0"
implementation "androidx.core:core:1.19.0"
}
إنشاء "نشاط مستمر"
تتضمّن العملية ثلاث خطوات:
- أنشئ
NotificationCompat.Builderعادية واضبطها على مستمرة. - أنشئ كائن
OngoingActivityواضبطه، مع تمرير أداة إنشاء الإشعارات إليه. - طبِّق "النشاط الجاري" على أداة إنشاء الإشعارات وانشر الإشعار الناتج.
إنشاء الإشعار وضبطه
ابدأ بإنشاء NotificationCompat.Builder. الخطوة الأساسية هي استدعاء
setOngoing(true) لتصنيفها كإشعار بنشاط مستمر في الخلفية. يمكنك أيضًا ضبط خصائص أخرى للإشعارات في هذه المرحلة، مثل الرمز الصغير والفئة.
// Create a PendingIntent to pass to the notification builder val pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, AlwaysOnActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Always On Service") .setContentText("Service is running in background") .setSmallIcon(R.drawable.animated_walk) // Category helps the system prioritize the ongoing activity .setCategory(NotificationCompat.CATEGORY_WORKOUT) .setContentIntent(pendingIntent) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setOngoing(true) // Important!
إنشاء OngoingActivity
بعد ذلك، أنشِئ مثيلاً من OngoingActivity باستخدام أداة الإنشاء الخاصة به. يتطلّب
OngoingActivity.Builder Context ومعرّف إشعار وNotificationCompat.Builder الذي أنشأته في الخطوة السابقة.
اضبط خصائص المفتاح التي سيتم عرضها على مساحات العرض الجديدة في واجهة المستخدم:
- الرموز المتحركة والثابتة: قدِّم رموزًا يتم عرضها على خلفية شاشة الساعة في الوضعَين النشط والمحيط.
- نية اللمس: هي
PendingIntentتعيد المستخدم إلى تطبيقك عندما ينقر على رمز "النشاط قيد التقدّم". يمكنك إعادة استخدامpendingIndentالذي تم إنشاؤه في الخطوة السابقة.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // Sets the icon that appears on the watch face in active mode. .setAnimatedIcon(R.drawable.animated_walk) // Sets the icon that appears on the watch face in ambient mode. .setStaticIcon(R.drawable.ic_walk) // Sets the tap target to bring the user back to the app. .setTouchIntent(pendingIntent) .build()
الردّ على الإشعار والمنشور
الخطوة الأخيرة هي ربط OngoingActivity بالإشعار ثم نشره. تعدّل الطريقة ongoingActivity.apply() أداة إنشاء الإشعارات الأصلية، وتضيف البيانات اللازمة ليتمكّن النظام من عرضها على المساحات الإضافية. بعد تطبيقها، يمكنك إنشاء الإشعار ونشره كالمعتاد.
// This call modifies notificationBuilder to include the ongoing activity data. ongoingActivity.apply(applicationContext) // Post the notification. startForeground(NOTIFICATION_ID, notificationBuilder.build())
إضافة نص حالة ديناميكي إلى مشغّل التطبيقات
يضيف الرمز السابق الرمز القابل للنقر إلى خلفية الساعة. لتقديم إشعارات أكثر تفصيلاً في الوقت الفعلي في قسم الأحداث الأخيرة ضمن مشغّل التطبيقات، أنشئ عنصر Status وأرفِقه بـ OngoingActivity. إذا لم توفّر Status مخصّصة، سيستخدم النظام تلقائيًا نص محتوى الإشعار (الذي تم ضبطه باستخدام setContentText()). لعرض نص ديناميكي، استخدِم Status.Builder. يمكنك تحديد سلسلة نموذجية تتضمّن عناصر نائبة وتوفير
Status.Part لتعبئة هذه العناصر النائبة. يمكن أن يكون Status.Part ديناميكيًا، مثل ساعة الإيقاف أو المؤقّت.
يوضّح المثال التالي كيفية إنشاء حالة تعرض "الركض لمدة [a stopwatch timer]":
// Define a template with placeholders for the activity type and the timer. val statusTemplate = "#type# for #time#" // Set the start time for a stopwatch. // Use SystemClock.elapsedRealtime() for time-based parts. val runStartTime = SystemClock.elapsedRealtime() val ongoingActivityStatus = Status.Builder() // Sets the template string. .addTemplate(statusTemplate) // Fills the #type# placeholder with a static text part. .addPart("type", Status.TextPart("Run")) // Fills the #time# placeholder with a stopwatch part. .addPart("time", Status.StopwatchPart(runStartTime)) .build()
أخيرًا، اربط هذا Status بحسابك OngoingActivity من خلال الاتصال بالرقم setStatus()
على OngoingActivity.Builder.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // ... // Add the status to the OngoingActivity. .setStatus(ongoingActivityStatus) .build()
تخصيصات إضافية
بالإضافة إلى Status، يمكنك تخصيص "النشاط المتواصل" أو الإشعارات بالطرق التالية. ومع ذلك، قد لا يتم استخدام هذه التخصيصات استنادًا إلى طريقة تنفيذ الشركة المصنّعة للجهاز الأصلي.
الإشعار المستمر
- تحدّد فئة النشاط المستمر أولوية هذا النشاط.
CATEGORY_CALL: مكالمة صوتية أو مكالمة فيديو واردة أو طلب مماثل للتواصل بشكل متزامنCATEGORY_NAVIGATION: خريطة أو اتجاهات مفصّلة-
CATEGORY_TRANSPORT: عنصر التحكّم في نقل الوسائط للتشغيل CATEGORY_ALARM: منبّه أو موقّتCATEGORY_WORKOUT: تمرين-
CATEGORY_LOCATION_SHARING: فئة مشاركة الموقع الجغرافي المؤقتة CATEGORY_STOPWATCH: ساعة توقّف
النشاط الجاري
رمز متحرك: صورة متجهة بالأبيض والأسود، ويُفضّل أن تكون الخلفية شفافة. يتم عرضها على خلفية شاشة الساعة في الوضع النشط. في حال عدم توفير الرمز المتحرّك، سيتم استخدام رمز الإشعارات التلقائي. تختلف أيقونة الإشعارات التلقائية من تطبيق إلى آخر.
الرمز الثابت: هو رمز متّجه بخلفية شفافة. يتم عرضها على خلفية شاشة الساعة في وضع الاستراحة. إذا لم يتم ضبط الرمز المتحرّك، سيتم استخدام الرمز الثابت على خلفية شاشة الساعة في الوضع النشط. في حال عدم توفيرها، سيتم استخدام رمز الإشعار. إذا لم يتم ضبط أي منهما، سيتم عرض استثناء. (سيظل مشغّل التطبيقات يستخدم رمز التطبيق).
OngoingActivityStatus: نص عادي أو
Chronometer. يظهر في قسم التطبيقات الحديثة في مشغّل التطبيقات. في حال عدم توفيرها، سيتم استخدام "نص السياق" للإشعار.نية اللمس: هي
PendingIntentتُستخدَم للرجوع إلى التطبيق إذا نقر المستخدم على رمز "النشاط الجاري". يتم عرضها على خلفية شاشة الساعة أو على رمز مشغّل التطبيقات. يمكن أن يختلف هذا الغرض عن الغرض الأصلي المستخدَم لتشغيل التطبيق. وفي حال عدم توفيره، يتم استخدام غرض المحتوى الخاص بالإشعار. إذا لم يتم ضبط أي منهما، سيتم عرض استثناء.
LocusId: معرّف يحدّد اختصار مشغّل التطبيقات الذي يتوافق معه النشاط الجاري. يظهر على مشغّل التطبيقات في قسم عمليات البحث الأخيرة أثناء استمرار النشاط. في حال عدم توفيرها، سيخفي مشغّل التطبيقات جميع عناصر التطبيق في قسم النشاطات الأخيرة من الحزمة نفسها ولن يعرض سوى "النشاط الجاري".معرّف النشاط الجاري: هو المعرّف المستخدَم لتمييز طلبات
fromExistingOngoingActivity()عندما يكون لدى التطبيق أكثر من نشاط جارٍ واحد.
تعديل نشاط مستمر
عليك تعديل "النشاط الجاري" للإشعار الحالي عندما تحتاج إلى تغيير الحالة، بدلاً من إنشاء إشعار جديد و"نشاط جاري" جديد. لتعديل "النشاط الجاري" والإشعار المنشور، استخدِم العنصر الذي أنشأته سابقًا واستدعِ update()، كما هو موضّح في المثال التالي:
ongoingActivity.update(context, newStatus)
في الحالات التي لا يمكن فيها تخزين مرجع إلى النشاط الجاري، تتوفّر طريقة ثابتة لاسترداد النشاط الجاري. ومع ذلك، لا ننصح باستخدام هذه الطريقة:
OngoingActivity.recoverOngoingActivity(context) ?.update(context, newStatus)
إيقاف "نشاط قيد التقدّم"
عندما ينتهي التطبيق من العمل كنشاط مستمر في الخلفية، ما عليه سوى إلغاء إشعار بنشاط مستمر في الخلفية.
يمكنك أيضًا اختيار إلغاء الإشعار أو "النشاط الجاري" عند ظهورهما في المقدّمة، ثم إعادة إنشائهما عند الرجوع إلى الخلفية، ولكن هذا الإجراء ليس ضروريًا.
إيقاف نشاط جارٍ مؤقتًا
إذا كان تطبيقك يتضمّن إجراء إيقاف مؤقت صريحًا، واصِل عرض "النشاط الجاري" بعد إلغاء الإيقاف المؤقت. بالنسبة إلى تطبيق لا يتضمّن إجراء إيقاف صريحًا، يجب إنهاء النشاط عند إيقافه مؤقتًا.
الاعتبارات الأساسية
يُرجى تذكُّر ما يلي عند استخدام واجهة برمجة التطبيقات "النشاط المتواصل":
اضبط رمزًا ثابتًا لـ "النشاط الجاري"، إما بشكل صريح أو كقيمة احتياطية باستخدام الإشعار. إذا لم تفعل ذلك، ستتلقّى
IllegalArgumentException.استخدِم رموزًا متّجهة باللونين الأبيض والأسود مع خلفيات شفافة.
اضبط هدفًا عند اللمس لـ "النشاط الجاري"، إما بشكل صريح أو كإجراء احتياطي باستخدام الإشعار. إذا لم تفعل ذلك، ستتلقّى
IllegalArgumentException.إذا كان تطبيقك يتضمّن أكثر من نشاط
MAIN LAUNCHERواحد تم تحديده في ملف البيان، عليك نشر اختصار ديناميكي وربطه بنشاطك المستمر باستخدامLocusId.
نشر إشعارات الوسائط عند تشغيل الوسائط على أجهزة Wear OS
إذا كان يتم تشغيل محتوى وسائط على جهاز Wear OS، انشر إشعارًا بالوسائط. يتيح ذلك للنظام إنشاء النشاط الجاري المقابل.
إذا كنت تستخدم Media3، سيتم نشر الإشعار تلقائيًا. إذا أنشأت إشعارك يدويًا، يجب أن يستخدم MediaStyleNotificationHelper.MediaStyle، ويجب أن يتم ملء نشاط الجلسة في MediaSession المقابل.
اقتراحات مخصصة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة.
- إنشاء إشعار {:#notification}
- التفاعل مع مستخدمي Wear OS بطرق جديدة باستخدام Ongoing Activity API
- إنشاء إشعار قابل للتوسعة {:#expandable-notification}