שימוש בהתראות Android

מעבדת קוד זו היא חלק מהקורס המתקדם של Android בקורס Kotlin. כדי להפיק את המקסימום מהקורס הזה, אם עובדים על מעבדות הקוד ברצף, לא חובה לעשות זאת. כל שיעורי הקוד של הקורסים מופיעים בדף הנחיתה המתקדם של Android ב-Kotlin codelabs.

מבוא

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

התראה אופיינית מורכבת מכותרת, מתיאור ומסמל. ההתראה יכולה לכלול גם פעולות שניתן ללחוץ עליהן, תשובה מהירה, תוכן ניתן להרחבה ותמונות.

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

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

בשיעור Lab זה תלמדו איך ליצור התראות ולהשתמש בהן באפליקציה ל-Android.

דברים שחשוב לדעת

כדאי שתכירו את:

  • איך לארז אפליקציות ל-Android ב-Kotlin. ספציפית, אפשר לעבוד עם Android SDK.
  • כיצד לתכנן אפליקציות באמצעות רכיבי הארכיטקטורה וקישור נתונים.
  • הבנה בסיסית של Broadcastמקלטs
  • הבנה בסיסית של AlertManager

מה תלמדו

  • איך ליצור, לעצב ולשלוח התראה.
  • איך מבטלים התראות.
  • איך יוצרים ערוצי התראות.
  • איך להוסיף פעולות מהירות להתראות.
  • איך להציג תגי התראות בסמל האפליקציה?

הפעולות שתבצעו:

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

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

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

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

כדי לקבל את האפליקציה לדוגמה, תוכלו:

משכפלים את המאגר מ-GitHub ועוברים לסניף Starter.

$  git clone https://github.com/googlecodelabs/android-kotlin-notifications


לחלופין, אפשר להוריד את המאגר כקובץ Zip, לכווץ אותו ולפתוח אותו ב-Android Studio.

להורדת קובץ Zip

  1. פותחים את האפליקציה ומפעילים אותה ב-Android Studio.

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

  1. יש לבדוק את קוד המקור. האפליקציה למתחילים כוללת פעילות יחידה בשם MainActivity. יש שלוש חבילות משנה בשם receiver, ui ו-util.

  • /מקלט – החבילה receiver כוללת שני מקלטי שידור בשם AlarmReceiver וSnoozeReceiver. האפליקציה AlarmReceiver מופעלת על ידי AlarmManager כדי לשלוח את ההתראה כשהטיימר בהגדרת המשתמש יסתיים. SnoozeReceiver מטפלת בלחיצה של המשתמש כדי להעביר את ההתראה למצב נודניק.
  • /ui – פעולה זו כוללת את EggTimerFragment שהוא חלק מממשק המשתמש של האפליקציה. EggTimerViewModel אחראי להפעלה ולביטול של הטיימר ולמשימות אחרות הקשורות למחזור החיים של האפליקציה.
  • /util – בחבילה הזו יש שני קבצים. ל-BindingUtils.kt יש מתאמים מחייבים כדי לאפשר קישור נתונים בין ממשק המשתמש של האפליקציה לבין ViewModel. ל-NotificationUtils.kt יש שיטות הרחבה ב-NotificationManager.

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

שלב 1: יצירת התראה בסיסית

במשימה הזו תיצרו הודעה חדשה, תגדירו הודעה למשתמש ותשלחו את ההודעה.

  1. פותחים את הכיתה NotificationUtils.kt ומוצאים את TODO: Step 1.1. ניתן למצוא משימות לביצוע ב-Codelab הזה ובקוד האפליקציה.
  2. בדיקת הפונקציה sendNotification() הנתונה. אתם מתכוונים להרחיב את פונקציית התוסף הזו ל-NotificationManager כדי לשלוח התראות.
//NotificationUtils.kt
// TODO: Step 1.1 extension function to send messages (GIVEN)
/**
 * Builds and delivers a notification.
 *
 * @param messageBody, notification text.
 * @param context, activity context.
 */
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
  1. קבלת מופע של יוצר ההתראות, העברה בהקשר של האפליקציה ומזהה ערוץ. מזהה הערוץ הוא ערך מחרוזת שמופיע בערוץ.

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

//NotificationUtils.kt
// TODO: Step 1.2 get an instance of NotificationCompat.Builder
val builder = NotificationCompat.Builder(
        applicationContext,
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. מגדירים את סמל ההתראות כך שייצג את האפליקציה, את הכותרת ואת טקסט התוכן של ההודעה שרוצים להעביר למשתמש. יוצגו אפשרויות נוספות להתאמה אישית של ההודעה עוד במעבדת הקוד, אבל זהו הסכום המינימלי שצריך להגדיר כדי לשלוח התראה.
//NotificationUtils.kt
   // TODO: Step 1.3 set title, text and icon to builder
   .setSmallIcon(R.drawable.cooked_egg)
   .setContentTitle(applicationContext.getString(R.string.notification_title))
   .setContentText(messageBody)
  1. לאחר מכן, צריך להתקשר ל-notify() עם מזהה ייחודי בשביל ההתראה ועם אובייקט Notification מהבונה שלך.

המזהה הזה מייצג את מופע ההתראות הנוכחי, והוא נדרש לעדכון או לביטול של ההתראה הזו. מאחר שלאפליקציה תהיה רק התראה פעילה אחת בכל זמן נתון, אפשר להשתמש באותו מזהה עבור כל ההתראות. כבר קיבלת קבוע למטרה זו בשם NOTIFICATION_ID ב-NotificationUtils.kt. חשוב לשים לב שאפשר להתקשר ישירות אל notify() כי מבצעים את השיחה מפונקציית תוסף באותה מחלקה.

//NotificationUtils.kt
   // TODO: Step 1.4 call notify to send the notification
    // Deliver the notification
    notify(NOTIFICATION_ID, builder.build())
  1. פותחים את ui/EggTimerViewModel.kt ומחפשים את הפונקציה startTimer(). פונקציה זו יוצרת התראה עם מרווח הזמן שנבחר כשהמשתמש מפעיל את הטיימר לביצים.
  2. בפונקציה זו תופיע התראה כשהמשתמש מפעיל את הטיימר. כדי להפעיל את הפונקציה sendNotification() שהוטמעה בעבר, יש צורך במופע של NotificationManager. NotificationManager הוא שירות מערכת שמספק את כל הפונקציות שנחשפות ל-API של ההתראות, כולל פונקציית התוסף שהוספת. יש לך אפשרות לשלוח, לבטל או לעדכן התראה בכל פעם שברצונך לבקש מופע של NotificationManager מהמערכת. יש להפעיל את הפונקציה sendNotification()| בהודעת ההודעה ובהקשר.
// EggTimerViewModel.kt
// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification

val notificationManager = ContextCompat.getSystemService(
    app, 
    NotificationManager::class.java
) as NotificationManager
                notificationManager.sendNotification(app.getString(R.string.timer_running), app)

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

  1. פותחים את logcat ומחפשים את "No Channel found". אמורה להופיע הודעת שגיאה על כך ש-egg_channel לא קיים. בשלבים הבאים ניתן לקבל מידע נוסף על ערוצי ההתראות ולפתור את הבעיה.

שלב 2: ערוצי ההתראות

החל מגרסה 26 של ה-API, כל ההתראות צריכות להיות מוקצות לערוץ. אם לוחצים לחיצה ארוכה על סמל מרכז האפליקציות, בוחרים פרטי אפליקציה ומקישים על התראות, תוצג רשימה של ערוצי התראות שמשויכים לאפליקציה. כרגע הרשימה ריקה כי האפליקציה לא יצרה ערוצים.

ערוצים מייצגים "type" של התראות — לדוגמה, טיימר הביצים יכול לשלוח התראה כשהביצה מוכנה לבישול, וגם משתמש בערוץ אחר כדי לשלוח התראות יומיות כדי להזכיר לכם לשטוף ביצים עם ארוחת הבוקר. כל ההתראות מערוץ מקובצות יחד, והמשתמשים יכולים לקבוע את הגדרות ההתראות לגבי ערוץ שלם. כך המשתמשים יכולים להתאים אישית את הגדרות ההתראות שלהם בהתאם לסוג ההתראה שמעניין אותם. לדוגמה, המשתמשים יכולים להשבית את ההתראות לגבי ארוחת הבוקר, אבל עדיין לבחור לראות את ההתראות מהטיימר.

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

בשלב 1.1 השתמשת ב-egg_notification_channel_id כערוץ ההתראות שלך, כך שנכון לעכשיו, עליך ליצור ולהתאים אישית את הגדרות ההתראות ואת ההתנהגות של הערוץ.

  1. פותחים את EggTimerFragment.kt ומחפשים את הפונקציה createChannel().
  2. יש להעביר את מזהה הערוץ הייחודי לבנייה של NotificationChannel.
  3. אפשר להעביר את השם של ערוץ ההתראות, שגם המשתמשים יראו אותו במסך הגדרות.
  4. כפרמטר האחרון, עוברים את רמת החשיבות של ערוץ ההתראות. רמות המיקוד יכוסו מאוחר יותר במעבדה זו, ולכן בינתיים ניתן להשתמש ב-NotificationManager.IMPORTANCE_LOW.
  5. על האובייקט notificationChannel מגדירים את הערך enableLights כ-True. הגדרה זו תפעיל את הנורות כשמוצגת התראה.
  6. באובייקט notificationChannel יש להגדיר את lightColor בצבע אדום כדי להציג אור אדום כשמוצגת התראה.
  7. באובייקט notificationChannel יש להגדיר את enableVibration כ-True כדי להפעיל רטט.
  8. באובייקט notificationChannel יש להגדיר את תיאור הערוץ כ-‘Time for breakfast'.
  9. אפשר לקבל מופע של NotificationManager בטלפון getSystemService().
  10. עליך להתקשר אל createNotificationChannel() ברחוב NotificationManager ולעבור את האובייקט notificationChannel שיצרת בשלב הקודם.
//EggTimerFragment.kt
private fun createChannel(channelId: String, channelName: String) {
    // TODO: Step 1.6 START create a channel
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val notificationChannel = NotificationChannel(
            channelId,
            channelName,
            // TODO: Step 2.4 change importance
            NotificationManager.IMPORTANCE_LOW
        )
        // TODO: Step 2.6 disable badges for this channel

        notificationChannel.enableLights(true)
        notificationChannel.lightColor = Color.RED
        notificationChannel.enableVibration(true)
        notificationChannel.description = "Time for breakfast"

        val notificationManager = requireActivity().getSystemService(
            NotificationManager::class.java
        )
        notificationManager.createNotificationChannel(notificationChannel)
    }
    // TODO: Step 1.6 END create channel
}
  1. אחר כך, כדי ליצור ערוץ, עליך לקרוא לפונקציה createChannel() שכתבת (שלב 1.7). פונקציה זו מקבלת שני פרמטרים, מזהה הערוץ ושם הערוץ. עליכם לחפש את מזהה הערוץ ואת שם הערוץ ממקורות המידע שכבר סופקו בפרויקט.
// EggTimerFragment.kt
    // TODO: Step 1.7 call createChannel
    createChannel(
          getString(R.string.egg_notification_channel_id),
          getString(R.string.egg_notification_channel_name)
    )
  1. אתם צריכים להעביר את מזהה הערוץ לכלי ליצירת התראות. כבר עשית זאת בשלב 1.2. אם תגדירו ערך שגוי כמזהה הערוץ, ההתראה תיכשל. יש לפתוח את NotificationUtils.kt כדי לאמת שמזהה הערוץ שהגדרת בעבר נכון.
// NotificationUtils.kt
val builder = NotificationCompat.Builder(
        applicationContext,
       // TODO: Step 1.8 verify the notification channel name
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. הפעילו את האפליקציה ותוכלו לראות שהאפליקציה שולחת התראה בכל פעם שאתם מפעילים את הטיימר.
  2. יש למשוך את שורת הסטטוס ולראות שהכותרת, התוכן והסמל של ההתראות מוגדרים כפי שהגדרתם בשלבים הקודמים.
  3. כדי לאמת את הערוץ החדש שנוצר, סוגרים את האפליקציה ומחפשים את סמל האפליקציה. לוחצים לחיצה ארוכה על סמל האפליקציה ובוחרים באפשרות פרטי האפליקציה.

  1. בוחרים באפשרות התראות מרשימת ההגדרות. אתם אמורים לראות ערוץ חדש בשם ביצים, מתחת להגדרה הצגת התראות.

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

שלב 3: הוספת התראות לאפליקציה

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

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

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

  1. פותחים את הפונקציה AlarmReceiver.kt שהיא NotificationManager וקוראים לפונקציה sendNotification() עם הפרמטרים של הטקסט וההקשר של ההודעות.
// AlarmReceiver.kt
   // TODO: Step 1.9 add call to sendNotification
   val notificationManager = ContextCompat.getSystemService(
       context, 
       NotificationManager::class.java
   ) as NotificationManager
             
   notificationManager.sendNotification(
       context.getText(R.string.eggs_ready).toString(), 
       context
   )
  1. אפשר גם להסיר את 'הבלטה' כי האפליקציה תשלח התראה כשהטיימר יסתיים.
// AlarmReceiver.kt
     // TODO: Step 1.10 [Optional] remove toast
//   Toast.makeText(
//       context, 
//       context.getText(R.string.eggs_ready),
//       Toast.LENGTH_SHORT
//   ).show()
  1. מפעילים את האפליקציה . אמורה להופיע התראה בכל פעם שאתם מפעילים את הטיימר ובכל פעם שהטיימר פועל.

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

  1. פותחים את EggTimerFragment.kt ומסירים את קוד ההתראות משלב 1.5.
// EggTimeViewModel.kt

// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification
// val notificationManager = ContextCompat.getSystemService(
//      app,
//      NotificationManager::class.java
// ) as NotificationManager
// notificationManager.sendNotification(app.getString(R.string.eggs_ready), app)
  1. מפעילים שוב את האפליקציה.
  2. מגדירים טיימר, מגדירים אותו ברקע וממתינים לסיום הזמן. תופיע התראה על כך. זו התראה שימושית מאוד.

שלב 4: הוספה של כוונת תוכן

  1. אם האפליקציה לא פועלת, מפעילים אותה שוב.
  2. לוחצים על ההתראה. הפעולה לא הצליחה!

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

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

  1. פותחים את NotificationUtils.kt ומחפשים את פונקציית התוסף sendNotification().
  2. יוצרים Intent עם applicationContext ואת הפעילות להפעלה, MainActivity::class.java.
// NotificationUtils.kt

fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
    // Create the content intent for the notification, which launches
    // this activity
   // TODO: Step 1.11 create intent
    val contentIntent = Intent(applicationContext, MainActivity::class.java)

יצרת את הכוונה, אך ההתראה מוצגת מחוץ לאפליקציה. כדי שכוונת הרכישה תפעל מחוץ לאפליקציה, צריך ליצור PendingIntent חדש.

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

  1. יש ליצור PendingIntent עם applicationContext, NOTIFICATION_ID, contentIntent שיצרת בשלב הקודם ועם הסימון PendingIntent. הסימון PendingIntent מציין אפשרות ליצור PendingIntent חדש או להשתמש בסימון קיים. עליך להגדיר את PendingIntent.FLAG_UPDATE_CURRENT כסימון מכיוון שאינך רוצה ליצור התראה חדשה אם קיימת התראה קיימת. כך תשנה את PendingIntent הנוכחי המשויך לכוונה שסיפקת.
// NotificationUtils.kt
   // TODO: Step 1.12 create PendingIntent
    val contentPendingIntent = PendingIntent.getActivity(
        applicationContext, 
        NOTIFICATION_ID,
        contentIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
    )
  1. יש להעביר את PendingIntent אל ההתראה. פעולה זו מתבצעת על ידי התקשרות ל-setContentIntent() ב-NotificationBuilder. עכשיו, כשלוחצים על ההתראה, מופעל ה-PendingIntent ופותחים את MainActivity.
  2. כמו כן, יש להגדיר את setAutoCancel() כ-true, כך שכאשר המשתמש מקיש על ההתראה, ההתראה נסגרת כשהיא מועברת לאפליקציה.
// NotificationUtils.kt
    // TODO: Step 1.13 set content intent
    .setContentIntent(contentPendingIntent)
    .setAutoCancel(true)
  1. מפעילים שוב את האפליקציה.
  2. מגדירים טיימר, מגדירים את האפליקציה ברקע וממתינים עד לקבלת ההתראה.
  3. כאשר תראה את ההתראה, לחץ על ההתראה על ידי הזזת שורת הסטטוס למטה, וראה כיצד האפליקציה מועברת לחזית.

שלב 5: ביטול ההתראה

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

כדי לפתור את הבעיה, תצטרכו למחוק את ההתראה הקודמת כשתפעילו טיימר חדש. תחילה עליך ליצור פונקציית תוסף נוספת ב-NotificationUtils.kt. ל-NotificationManager יש API כדי לבטל את כל ההתראות הפעילות שנקראות cancelAll().

  1. פתיחת NotificationsUtil.kt
  2. יש להוסיף פונקציית תוסף במכשיר NotificationManager שמתקשר אל cancelAll().
// NotificationUtils.kt

// TODO: Step 1.14 Cancel all notifications
/**
 * Cancels all notifications.
 *
 */
fun NotificationManager.cancelNotifications() {
    cancelAll()
}
  1. פותחים את EggTimerViewModel.kt ומנווטים לפונקציה startTimer().
  2. בתוך startTimer(), יש לקבל מופע של NotificationManager מהמערכת ולהתקשר אל cancelNotifications().
//  EggTimerViewModel.kt
   //TODO Step 1.15 call cancel notification
    val notificationManager =
       ContextCompat.getSystemService(
            app,
            NotificationManager::class.java
        ) as NotificationManager
    notificationManager.cancelNotifications()       
  1. מפעילים את האפליקציה ומפעילים את הטיימר.
  2. אחרי שתפעילו את ההתראה, תצטרכו להפעיל מחדש את הטיימר ולראות איך ההודעה הקודמת נמחקת באופן אוטומטי משורת הסטטוס.

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

שלב 1: עיצוב ההתראה

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

ב-NotificationCompat יש סגנונות מובנים עבור:

  • BigTextStyle, שיכול להציג בלוק גדול של טקסט, כמו הצגת התוכן של הודעות אימייל כאשר הן מורחבות.
  • BigPictureStyle, שמציג התראות בפורמט גדול שכוללות קובץ מצורף של תמונה גדולה.
  • InboxStyle, שמציג תוכן טקסט בסגנון שיחה.
  • MediaStyle, שכולל פקדים להפעלת מדיה.
  • MessagingStyle, שמציג הודעות בפורמט גדול שכוללות מספר הודעות בין מספר אנשים.

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

  1. פותחים את NotificationUtils.kt ומחפשים את הפונקציה sendNotification().
  2. התחל בטעינת תמונה מ-resources באמצעות BitmapFactory.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
  1. יצירת BigPictureStyle חדש והגדרת תמונה.
  2. יש להגדיר את bigLargeIcon() ל-null כדי שהסמל הגדול ייעלם כשההתראה מורחבת.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
val bigPicStyle = NotificationCompat.BigPictureStyle()
        .bigPicture(eggImage)
        .bigLargeIcon(null)
  1. מגדירים את הסגנון באמצעות setStyle() ל-bigPicStyle.
  2. יש להגדיר את הסמל הגדול כ-setLargeIcon() ל-eggImage, כך שהתמונה תוצג כסמל קטן יותר כשהמודעה קורסת.
// NotificationUtils.kt
// TODO: Step 2.1 add style to builder
.setStyle(bigPicStyle)
.setLargeIcon(eggImage)
  1. מפעילים את האפליקציה ומגדירים טיימר. כאשר ההתראה מוצגת בפעם הראשונה, היא במצב מכווץ (חלונית הזזה) של ההתראה. כשמרחיבים את ההתראה, מוצגת תמונה גדולה באזור ההתראות המורחב.

שלב 2: פעולות הקשורות להתראות

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

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

כדי להוסיף לחצן פעולה, מעבירים PendingIntent לפונקציה addAction() בכלי ליצירת פעולות. הפעולה הזו דומה להגדרת פעולת ברירת המחדל בהקשה על ההתראה: יש לבצע setContentIntent() פעולות נוספות במקום להפעיל פעילות, למשל להפעיל BroadcastReceiver ברקע, שמבצע פעולה ברקע, כדי שהפעולה לא תפריע לפעולה שכבר פתוחה.

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

  1. פתיחת SnoozeReceiver.kt השיעור הזה דומה ל-AlarmReceiver שבו השתמשת בעבר. בשלבים הבאים עליך להוסיף קוד שיפעיל את הפונקציה onReceive() ב-SnoozeReceiver. בקצרה, הקוד ב-SnoozeReceiver ייצור התראה חדשה לשליחת התראה חדשה לאחר דקה. גוללים לתחתית של הפונקציה onGet, מקבלים מופע של messageManager מהמערכת ומגדירים ביטול של AllAll.
// SnoozeReceiver.kt
        val notificationManager = ContextCompat.getSystemService(
            context,
            NotificationManager::class.java
        ) as NotificationManager
        notificationManager.cancelAll()
  1. כדי להשתמש ב-SnoozeReceiver, יש לפתוח את NotificationUtils.kt.
  2. יש ליצור Intent snoozeIntent חדש עבור SnoozeReceiver מיד אחרי הסגנון בפונקציה sendNotification().
  3. כדי ליצור כוונות בהמתנה, יש להפעיל את שיטת getBroadcast() ב-PendingIntent. הפרמטרים האלה מצפים לפרמטרים בשלבים הבאים. המערכת תשתמש ב-PendingIntent הזה כדי להגדיר התראה חדשה לפרסום התראה חדשה לאחר 60 שניות, שהמשתמש מקיש על לחצן ההשהיה.
  4. הפרמטר הראשון הוא ההקשר של האפליקציה שבה PendingIntent צריך להתחיל את הפעילות.
  5. הפרמטר השני הוא קוד הבקשה, שהוא קוד הבקשה ל-Intent בהמתנה. אם צריך לעדכן או לבטל את הכוונה בהמתנה, צריך להשתמש בקוד הזה כדי לגשת ל-Intent בהמתנה.
  6. בשלב הבא יש להוסיף את האובייקט snoozeIntent, שהוא הכוונה של הפעילות שיושקה.
  7. לסיום, מוסיפים את ערך הסימון של #FLAG_ONE_SHOT כי כוונת הרכישה תשמש פעם אחת בלבד. הפעולה המהירה וההתראה יעלמו אחרי ההקשה הראשונה, ולכן ניתן להשתמש בהגדרה הזו רק פעם אחת.
// NotificationUtils.kt

// TODO: Step 2.2 add snooze action
val snoozeIntent = Intent(applicationContext, SnoozeReceiver::class.java)
val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(
    applicationContext, 
    REQUEST_CODE, 
    snoozeIntent, 
    FLAGS
)
  1. בשלב הבא, יש לקרוא לפונקציה addAction() ב-notificationBuilder. הפונקציה הזו מצפה לסמל ולטקסט שמתאר את הפעולה שלכם למשתמש. צריך להוסיף גם את snoozeIntent. פעולה זו תשמש להפעלת boadcastReceiver הנכונים בעת לחיצה על הפעולה שלך.
// NotificationUtils.kt
// TODO: Step 2.3 add snooze action
.addAction(
    R.drawable.egg_icon, 
    applicationContext.getString(R.string.snooze),
    snoozePendingIntent
)
  1. מריצים את אפליקציית הטיימר לביצים כדי לבדוק את פעולת ההשהיה.
  2. מכוונים את הטיימר ומגדירים את האפליקציה ברקע. כשיסתיים הזמן, הטיימר ירחיב את ההתראה ויראה שההודעה כוללת עכשיו לחצן 'לטיפול בהמשך' שמשהה את טיימר הביצים למשך דקה נוספת.

שלב 3: החשיבות של ההתראות

מידת החשיבות קובעת את מידת ההשפעה האפשרית של ההתראה על המשתמש מבחינה חזותית וקולית. התראות עם חשיבות גבוהה יותר יפריעו יותר למשתמשים.

יש לציין את רמת החשיבות בבונה NotificationChannel. במקור הגדרת חשיבות נמוכה באפליקציה של טיימר הביצים. אפשר להשתמש באחת מחמש רמות חשיבות, החל מ-IMPORTANCE_NONE(0) ועד IMPORTANCE_HIGH(4). רמת החשיבות שאתם מקצים לערוץ חלה על כל ההודעות שאתם מפרסמים בערוץ.

הרמות של חשיבות הערוץ

רמת חשיבות המוצגת למשתמש

חשיבות (Android 8.0 ואילך)

עדיפות (Android 7.1 ומטה)

שומעים צליל ומוצגת כהתראה מראש (מופיעה בחלק העליון של המסך)

IMPORTANCE_high

PRIORITY_גבוה / PRIORITY_MAX

משמיע צליל

IMPORTANCE_DEFAULT

PRIORITY_DEFAULT

ללא צלילים

IMPORTANCE_LOW

PRIORITY_LOW

לא נשמע צליל ולא מופיע בשורת הסטטוס

IMPORTANCE_MIN

PRIORITY_MIN

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

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

  1. כדי לשנות את רמת החשיבות של ערוץ ההתראות של האפליקציה, יש לפתוח את EggTimerFragment.kt ולנווט אל createChannel(). שינוי רמת החשיבות מIMPORTANCE_LOW לIMPORTANCE_HIGH.
// EggTimerFragment.kt
    val notificationChannel = NotificationChannel(
        channelId,
        channelName,
        // TODO: Step 2.4 change importance
        NotificationManager.IMPORTANCE_HIGH
    )

כדי לתמוך במכשירים עם Android מגרסה 7.1 (רמת API 25) ומטה, צריך גם לקרוא ל-setPriority() בכל התראה באמצעות הגדרה קבועה מראש מהמחלקה NotificationCompat.

  1. פותחים את NotificationUtils.kt ומוסיפים את הפריטים הבאים לאובייקט של התראה.
// NotificationUtils.kt
   .addAction(
       R.drawable.common_google_signin_btn_icon_dark,
       applicationContext.getString(R.string.snooze),
       snoozePendingIntent
    )
   // TODO: Step 2.5 set priority
    .setPriority(NotificationCompat.PRIORITY_HIGH)
  1. לפני הפעלת האפליקציה, לוחצים לחיצה ארוכה על סמל האפליקציה במכשיר או באמולטור ובוחרים באפשרות 'הסרה' כדי לנקות את הגדרות הערוץ הקודמות. אם האפליקציה לא תוסר, הגדרות העדיפות של הערוץ לא ישתנו. בעקבות זאת, לא יהיה שינוי בהתנהגות לאחר פרסום ההודעה.
  2. עכשיו מפעילים שוב את האפליקציה ומפעילים את הטיימר. הפעם, כשההתראה נשלחת, אמור להופיע חלון קופץ בחלק העליון של המסך, בין אם האפליקציה פועלת בחזית או ברקע.

שלב 4: תגי התראות

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

הנקודות האלה, שנקראות תגים, מופיעות כברירת מחדל ואין צורך לבצע פעולה כלשהי באפליקציה. עם זאת, ייתכנו מצבים שבהם תגים לא יהיו הגיוניים עבור ההתראות שלך, כך שתהיה לך אפשרות להשבית אותם על בסיס כל ערוץ על ידי התקשרות ל-setShowBadge(false) באובייקט NotificationChannel. כיוון שטיימר של ביצה כולל רק התראה פעילה אחת בכל רגע נתון, התג בסמל האפליקציה לא מציע הרבה יתרונות למשתמשים. בשלבים הבאים תשבית את התג ותציג הודעה רק עבור טיימר הביצים.

  1. כדי להשבית תגים, צריך להוסיף את setShowBadge(false) לקוד יצירת הערוץ לטיימר לביצים.
// EggTimerFragment.kt

    ).apply {
        // TODO: Step 2.6 disable badges for this channel
        setShowBadge(false)
    }
  1. מפעילים את האפליקציה שוב, מפעילים את הטיימר וצופים בסמל האפליקציה. לא אמור להופיע תג על סמל האפליקציה.

קוד הפתרון מופיע בהסניף הראשי של הקוד שהורדתם.

קורס אוניברסיטה:

התיעוד של מפתח Android:

קישורים למעבדות אחרות של הקוד בקורס הזה זמינים בדף הנחיתה של מכשירי Android מתקדמים בדף Kotlin codelabs.