הצגת פעילויות מתמשכות

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

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

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

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

החל מ-Wear OS 7, הפתרון הוא לשייך התראה מתמשכת לOngoingActivity או להתראה על עדכון בזמן אמת. כך המכשיר יכול להציג מידע על הפעילות שמתבצעת לאורך זמן בממשק המשתמש, ולהפעיל תכונות כמו הסמל שאפשר להקיש עליו בתחתית של תצוגת השעון. האינדיקטור הזה מאפשר למשתמשים לדעת על המשימה שפועלת ברקע, ומספק דרך לחזור לאפליקציה בלחיצה אחת.

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

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

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

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

חשוב: השימוש בOngoingActivity או בעדכון בזמן אמת בתרחישים האלה הוא דרישה במסגרת ההנחיות לאיכות אפליקציות ל-Wear OS‏ WO-V4.

לדוגמה, באפליקציית אימון הכושר הזו, המידע יכול להופיע בתצוגת השעון של המשתמש כסמל של ריצה שאפשר להקיש עליו:

running-icon

איור 1. אינדיקטור של פעילות.

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

מרכז האפליקציות

איור 2. מרכז האפליקציות הגלובלי.

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

טיימר

איור 3. טיימר: סופר לאחור את הזמן ומסתיים כשהטיימר מושהה או מופסק.

מפה

איור 4. מסלול מפורט: הכרזה על הוראות הגעה ליעד. השיתוף מסתיים כשהמשתמש מגיע ליעד או מפסיק את הניווט.

מוזיקה

איור 5. מדיה: השמעת מוזיקה במהלך הסשן. הסשן מסתיים מיד אחרי שהמשתמש משהה אותו.

מערכת Wear יוצרת באופן אוטומטי פעילויות מתמשכות לאפליקציות מדיה.

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

הגדרה

כדי להתחיל להשתמש ב-Ongoing Activity API באפליקציה, מוסיפים את התלות הבאה לקובץ build.gradle של האפליקציה:

dependencies {
  implementation "androidx.wear:wear-ongoing:1.1.0"
  implementation "androidx.core:core:1.19.0"
}

יצירת פעילות מתמשכת

התהליך כולל שלושה שלבים:

  1. יוצרים NotificationCompat.Builder רגיל ומגדירים אותו כמתמשך.
  2. יוצרים ומגדירים אובייקט OngoingActivity ומעבירים אליו את ה-builder של ההתראה.
  3. מחילים את הפעילות המתמשכת על כלי ליצירת התראות ומפרסמים את ההתראה שנוצרת.

יצירה והגדרה של ההתראה

קודם כל יוצרים 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. אפשר להגדיר מחרוזת תבנית עם placeholders ולספק אובייקטים של Status.Part כדי למלא את ה-placeholders האלה. האפשרות Status.Part יכולה להיות דינמית, כמו שעון עצר או טיימר.

בדוגמה הבאה מוצג אופן יצירת סטטוס עם הכיתוב 'פועל במשך [שעון עצר]':

// 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. מוצג בקטע האחרונות במרכז האפליקציות. אם לא מספקים את הטקסט הזה, המערכת משתמשת ב"טקסט ההקשר" של ההתראה.

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

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

  • Ongoing Activity ID: מזהה שמשמש להבחנה בין קריאות ל-fromExistingOngoingActivity() כשיש לאפליקציה יותר מפעילות מתמשכת אחת.

עדכון פעילות מתמשכת

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

ongoingActivity.update(context, newStatus)

במקרים שבהם אי אפשר לשמור הפניה ל-OngoingActivity, יש שיטה סטטית לשחזור הפעילות המתמשכת. עם זאת, האפשרות הזו פחות מועדפת:

OngoingActivity.recoverOngoingActivity(context)
    ?.update(context, newStatus)

איך מפסיקים פעילות מתמשכת

כשהאפליקציה מסיימת לפעול כפעילות מתמשכת, היא צריכה רק לבטל את ההתראה המתמשכת.

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

השהיית פעילות מתמשכת

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

שיקולים עיקריים

כשעובדים עם Ongoing Activity API, חשוב לזכור את הדברים הבאים:

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

  • שימוש בסמלי וקטור בשחור-לבן עם רקע שקוף.

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

  • אם באפליקציה יש יותר מפעילות אחת MAIN LAUNCHER שמוצהרת במניפסט, צריך לפרסם קיצור דרך דינמי ולשייך אותו לפעילות המתמשכת באמצעות LocusId.

פרסום התראות על מדיה כשמפעילים מדיה במכשירי Wear OS

אם תוכן מדיה מופעל במכשיר Wear OS, מפרסמים התראה על מדיה. כך המערכת יכולה ליצור את הפעילות המתאימה שמתבצעת באופן שוטף.

אם אתם משתמשים ב-Media3, ההתראה מתפרסמת באופן אוטומטי. אם יוצרים את ההתראה באופן ידני, צריך להשתמש ב-MediaStyleNotificationHelper.MediaStyle, וב-MediaSession המתאים צריך להיות מאוכלס session activity.