יצירת התראה

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

הקוד בדף הזה משתמש בממשקי ה-API של NotificationCompat מספריית AndroidX. ממשקי ה-API האלה מאפשרים לכם להוסיף תכונות שזמינות רק בגרסאות חדשות יותר של Android, ועדיין לשמור על תאימות ל-Android 9 (רמת API 28). עם זאת, חלק מהתכונות, כמו פעולת התשובה בתוך השורה, גורמות לאי-הפעלה בגרסאות קודמות.

הוספת ספריית הליבה של AndroidX

רוב הפרויקטים שנוצרים באמצעות Android Studio כוללים את יחסי התלות הנדרשים לשימוש ב-NotificationCompat, אבל חשוב לוודא שקובץ build.gradle ברמת המודול כולל את יחסי התלות הבאים:

מגניב

dependencies {
    implementation "androidx.core:core:2.2.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-ktx:2.2.0")
}

יצירת התראה בסיסית

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

איור 1. התראה עם סמל, כותרת וטקסט.

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

הצהרה על ההרשאה בזמן הריצה

ב-Android 13 ואילך (רמת API 33 ואילך) יש תמיכה בהרשאה בסביבת זמן ריצה לפרסום התראות לא פטורות (כולל שירותים שפועלים בחזית (FGS)) מאפליקציה.

ההרשאה שעליה צריך להצהיר בקובץ המניפסט של האפליקציה מופיעה בקטע הקוד הבא:

<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>

למידע נוסף על הרשאות בתחילת ההפעלה, ראו הרשאה בתחילת ההפעלה של התראות.

הגדרת תוכן ההתראות

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

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

  • שם, שהוגדר על ידי setContentTitle().

  • גוף הטקסט, שמוגדר על ידי setContentText().

  • רמת העדיפות של ההתראה, שהוגדרה על ידי setPriority(). העדיפות קובעת את מידת ההפרעה של ההתראה ב-Android 7.1 וגרסאות קודמות. ב-Android מגרסה 8.0 ואילך, צריך להגדיר את מידת החשיבות של הערוץ במקום זאת, כפי שמתואר בקטע הבא.

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

ב-constructor של NotificationCompat.Builder צריך לציין מזהה ערוץ. הקוד הזה נדרש לצורך תאימות ל-Android מגרסה 8.0 (רמת API‏ 26) ואילך, אבל הוא מתעלם מגרסאות קודמות.

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

איור 2. התראה שניתן להרחיב במצבים מכווץ ומורחב.

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

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(new NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

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

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

כדי שתוכלו לשלוח את ההתראה ב-Android מגרסה 8.0 ואילך, עליכם לרשום את ערוץ ההתראות של האפליקציה במערכת. לשם כך, מעבירים מופע של NotificationChannel אל createNotificationChannel(). הקוד הבא חסום על ידי תנאי בגרסה SDK_INT:

Kotlin

private fun createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = getString(R.string.channel_name)
        val descriptionText = getString(R.string.channel_description)
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
            description = descriptionText
        }
        // Register the channel with the system.
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

Java

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this.
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

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

ב-constructor של NotificationChannel נדרש importance, באמצעות אחד מהקבועים מהקלאס NotificationManager. הפרמטר הזה קובע איך להפריע למשתמש בכל התראה ששייכת לערוץ הזה. מגדירים את העדיפות באמצעות setPriority() כדי לתמוך ב-Android 7.1 ומטה, כפי שמתואר בדוגמה הקודמת.

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

למידע נוסף על המשמעות של הרמות השונות, קראו את המאמר רמות של חשיבות התראות.

הגדרת הפעולה של הקשה על ההתראה

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

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

Kotlin

// Create an explicit intent for an Activity in your app.
val intent = Intent(this, AlertDetails::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)

val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)

Java

// Create an explicit intent for an Activity in your app.
Intent intent = new Intent(this, AlertDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

הקוד הזה קורא ל-setAutoCancel(), שמאפשר להסיר את ההתראה באופן אוטומטי כשהמשתמש מקייש עליה.

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

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

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

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

הצגת ההתראה

כדי להציג את ההתראה, צריך להפעיל את הפונקציה NotificationManagerCompat.notify() ולהעביר לה מזהה ייחודי של ההתראה ואת התוצאה של NotificationCompat.Builder.build(). הדוגמה הבאה ממחישה זאת:

Kotlin

with(NotificationManagerCompat.from(this)) {
    if (ActivityCompat.checkSelfPermission(
            this@MainActivity,
            Manifest.permission.POST_NOTIFICATIONS
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // TODO: Consider calling
        // ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
        //                                        grantResults: IntArray)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.

        return@with
    }
    // notificationId is a unique int for each notification that you must define.
    notify(NOTIFICATION_ID, builder.build())
}

Java

with(NotificationManagerCompat.from(this)) {
   if (ActivityCompat.checkSelfPermission(
           this@MainActivity,
           Manifest.permission.POST_NOTIFICATIONS
       ) != PackageManager.PERMISSION_GRANTED
   ) {
       // TODO: Consider calling
       // ActivityCompat#requestPermissions
       // here to request the missing permissions, and then overriding
       // public void onRequestPermissionsResult(int requestCode, String[] permissions,
       //                                        int[] grantResults)
       // to handle the case where the user grants the permission. See the documentation
       // for ActivityCompat#requestPermissions for more details.

       return
   }
   // notificationId is a unique int for each notification that you must define.
   notify(NOTIFICATION_ID, builder.build())
}

שומרים את מזהה ההתראה שמעבירים ל-NotificationManagerCompat.notify(), כי תצטרכו אותו כשתרצו לעדכן או להסיר את ההתראה.

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

הוספת לחצני פעולה

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

איור 3. התראה עם לחצן פעולה אחד.

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

לדוגמה, הקוד הבא מראה איך לשלוח שידור למקלט ספציפי:

Kotlin

val ACTION_SNOOZE = "snooze"

val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
    action = ACTION_SNOOZE
    putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
    PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent)

Java

String ACTION_SNOOZE = "snooze"

Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
        PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent);

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

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

הוספת פעולה לתשובה ישירה

פעולת המענה הישיר, שהושקה ב-Android 7.0 (רמת API 24), מאפשרת למשתמשים להזין טקסט ישירות בהודעה. לאחר מכן, הטקסט מועבר לאפליקציה בלי לפתוח פעילות. לדוגמה, אפשר להשתמש בפעולה של תשובה ישירה כדי לאפשר למשתמשים להשיב להודעות טקסט או לעדכן רשימות משימות מתוך ההתראה.

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

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

הוספת לחצן התשובה

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

  1. יוצרים מופע של RemoteInput.Builder שאפשר להוסיף לפעולה של ההתראה. ה-constructor של המחלקה הזה מקבל מחרוזת שהמערכת משתמשת בה כמפתח לקלט הטקסט. בהמשך, האפליקציה תשתמש במקש הזה כדי לאחזר את הטקסט של הקלט.

    Kotlin

      // Key for the string that's delivered in the action's intent.
      private val KEY_TEXT_REPLY = "key_text_reply"
      var replyLabel: String = resources.getString(R.string.reply_label)
      var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
          setLabel(replyLabel)
          build()
      }
      

    Java

      // Key for the string that's delivered in the action's intent.
      private static final String KEY_TEXT_REPLY = "key_text_reply";
    
      String replyLabel = getResources().getString(R.string.reply_label);
      RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
              .setLabel(replyLabel)
              .build();
      
  2. יוצרים PendingIntent לפעולה של שליחת התשובה.

    Kotlin

      // Build a PendingIntent for the reply action to trigger.
      var replyPendingIntent: PendingIntent =
          PendingIntent.getBroadcast(applicationContext,
              conversation.getConversationId(),
              getMessageReplyIntent(conversation.getConversationId()),
              PendingIntent.FLAG_UPDATE_CURRENT)
      

    Java

      // Build a PendingIntent for the reply action to trigger.
      PendingIntent replyPendingIntent =
              PendingIntent.getBroadcast(getApplicationContext(),
                      conversation.getConversationId(),
                      getMessageReplyIntent(conversation.getConversationId()),
                      PendingIntent.FLAG_UPDATE_CURRENT);
      
  3. מחברים את האובייקט RemoteInput לפעולה באמצעות addRemoteInput().

    Kotlin

      // Create the reply action and add the remote input.
      var action: NotificationCompat.Action =
          NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
              getString(R.string.label), replyPendingIntent)
              .addRemoteInput(remoteInput)
              .build()
      

    Java

      // Create the reply action and add the remote input.
      NotificationCompat.Action action =
              new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
                      getString(R.string.label), replyPendingIntent)
                      .addRemoteInput(remoteInput)
                      .build();
      
  4. מחילים את הפעולה על התראה ומפעילים אותה.

    Kotlin

      // Build the notification and add the action.
      val newMessageNotification = Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build()
    
      // Issue the notification.
      with(NotificationManagerCompat.from(this)) {
          notificationManager.notify(notificationId, newMessageNotification)
      }
      

    Java

      // Build the notification and add the action.
      Notification newMessageNotification = new Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build();
    
      // Issue the notification.
      NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
      notificationManager.notify(notificationId, newMessageNotification);
      

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

אחזור הקלט של המשתמש מהתשובה

כדי לקבל קלט מהמשתמש מממשק המשתמש של התשובה להתרעה, צריך להפעיל את RemoteInput.getResultsFromIntent() ולהעביר לו את ה-Intent שהתקבל על ידי BroadcastReceiver:

Kotlin

private fun getMessageText(intent: Intent): CharSequence? {
    return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
}

Java

private CharSequence getMessageText(Intent intent) {
    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
    if (remoteInput != null) {
        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
    }
    return null;
 }

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

Kotlin

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build()

// Issue the new notification.
NotificationManagerCompat.from(this).apply {
    notificationManager.notify(notificationId, repliedNotification)
}

Java

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
Notification repliedNotification = new Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build();

// Issue the new notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, repliedNotification);

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

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

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

הוספת סרגל התקדמות

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

איור 5. סרגל ההתקדמות במהלך פעולה.

אם אתם יכולים להעריך את מידת ההתקדמות של הפעולה בכל שלב, תוכלו להשתמש בפורמט 'החלטתי' של האינדיקטור – כפי שמוצג באיור 5 – על ידי קריאה ל-setProgress(max, progress, false). הפרמטר הראשון הוא הערך של 'complete', למשל 100. השני הוא ההתקדמות בעבודה. הערך האחרון מציין שמדובר בסרגל התקדמות מוגדר.

במהלך הפעולה, צריך להפעיל את setProgress(max, progress, false) באופן קבוע עם ערך מעודכן של progress ולשלוח מחדש את ההתראה, כפי שמתואר בדוגמה הבאה.

Kotlin

val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
    setContentTitle("Picture Download")
    setContentText("Download in progress")
    setSmallIcon(R.drawable.ic_notification)
    setPriority(NotificationCompat.PRIORITY_LOW)
}
val PROGRESS_MAX = 100
val PROGRESS_CURRENT = 0
NotificationManagerCompat.from(this).apply {
    // Issue the initial notification with zero progress.
    builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
    notify(notificationId, builder.build())

    // Do the job that tracks the progress here.
    // Usually, this is in a worker thread.
    // To show progress, update PROGRESS_CURRENT and update the notification with:
    // builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
    // notificationManager.notify(notificationId, builder.build());

    // When done, update the notification once more to remove the progress bar.
    builder.setContentText("Download complete")
            .setProgress(0, 0, false)
    notify(notificationId, builder.build())
}

Java

...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setContentTitle("Picture Download")
        .setContentText("Download in progress")
        .setSmallIcon(R.drawable.ic_notification)
        .setPriority(NotificationCompat.PRIORITY_LOW);

// Issue the initial notification with zero progress.
int PROGRESS_MAX = 100;
int PROGRESS_CURRENT = 0;
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
notificationManager.notify(notificationId, builder.build());

// Do the job that tracks the progress here.
// Usually, this is in a worker thread.
// To show progress, update PROGRESS_CURRENT and update the notification with:
// builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, builder.build());

// When done, update the notification once more to remove the progress bar.
builder.setContentText("Download complete")
        .setProgress(0,0,false);
notificationManager.notify(notificationId, builder.build());

בסוף הפעולה, הערך של progress חייב להיות שווה ל-max. אפשר להשאיר את סרגל ההתקדמות כדי להראות שהפעולה הסתיימה או להסיר אותו. בכל מקרה, צריך לעדכן את הטקסט של ההתראה כך שיציין שהפעולה הושלמה. כדי להסיר את סרגל ההתקדמות, צריך להפעיל את הפונקציה setProgress(0, 0, false).

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

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

הגדרת קטגוריה ברמת המערכת

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

אם ההתראה שייכת לאחת מקטגוריות ההתראות שמוגדרות ב-NotificationCompat, למשל CATEGORY_ALARM, CATEGORY_REMINDER, CATEGORY_EVENT או CATEGORY_CALL – ציינו את הקטגוריה המתאימה על ידי העברת הקטגוריה המתאימה אל setCategory():

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE);

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

הצגת הודעה דחופה

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

כשהתראה מופעלת, המשתמשים רואים אחת מההודעות הבאות, בהתאם למצב הנעילה של המכשיר:

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

קטע הקוד הבא מראה איך לשייך את ההתראה ל-Intent במסך מלא:

Kotlin

val fullScreenIntent = Intent(this, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true)

Java

Intent fullScreenIntent = new Intent(this, ImportantActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
        fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true);

הגדרת הרשאות הגישה למסך הנעילה

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

  • VISIBILITY_PUBLIC: התוכן המלא של ההתראה מוצג במסך הנעילה.

  • VISIBILITY_SECRET: לא מופיע חלק מההתראה במסך הנעילה.

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

כשמגדירים את VISIBILITY_PRIVATE, אפשר גם לספק גרסה חלופית של תוכן ההתראות שמסתירת פרטים מסוימים. לדוגמה, אפליקציית SMS עשויה להציג התראה עם הכיתוב 'יש לך 3 הודעות טקסט חדשות', אבל להסתיר את תוכן ההודעות ואת השולחים. כדי לשלוח את ההתראה החלופית הזו, קודם יוצרים את ההתראה החלופית באמצעות NotificationCompat.Builder כרגיל. לאחר מכן, מצרפים את ההתראה החלופית להתראה הרגילה באמצעות setPublicVersion().

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

עדכון התראה

כדי לעדכן התראה אחרי שהיא נשלחה, צריך לבצע קריאה חוזרת ל-NotificationManagerCompat.notify() ולהעביר לה את אותו מזהה שבו השתמשתם קודם. אם ההתראה הקודמת תיסגר, במקום זאת תיווצר התראה חדשה.

אפשר גם לקרוא ל-setOnlyAlertOnce() כדי שההתראה תפריע למשתמש – באמצעות צליל, רטט או רמזים חזותיים – רק בפעם הראשונה שמופיעה ההתראה ולא לעדכונים מאוחרים יותר.

הסרת התראה

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

  • המשתמש סוגר את ההתראה.
  • המשתמש מקייש על ההתראה, אם קוראים לפונקציה setAutoCancel() בזמן יצירת ההתראה.
  • קוראים ל-cancel() עם מזהה התראה ספציפי. השיטה הזו מוחקת גם התראות קיימות.
  • מתקשרים למספר cancelAll(), ומבטלים את כל ההתראות ששלחתם בעבר.
  • משך הזמן שצוין חולף, אם מגדירים זמן קצוב לתפוגה כשיוצרים את ההתראה באמצעות setTimeoutAfter(). אם צריך, אפשר לבטל התראה לפני שפג תוקף הזמן הקצוב לתפוגה.

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

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

שימוש ב-MessagingStyle

החל מ-Android 7.0 (רמת API 24), מערכת Android מספקת תבנית של סגנון התראות שמיועדת ספציפית לתוכן של הודעות. במחלקה NotificationCompat.MessagingStyle אפשר לשנות כמה מהתוויות שמוצגות בהתראה, כולל את כותרת השיחה, הודעות נוספות ותצוגת התוכן של ההתראה.

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

Kotlin

val user = Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build()

val notification = NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with $sender")
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build()

Java

Person user = new Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build();

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with " + sender)
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(new NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build();

החל מ-Android 9.0 (רמת API 28), צריך גם להשתמש בכיתה Person כדי לקבל רינדור אופטימלי של ההתראה והסמלים שלה.

כשמשתמשים ב-NotificationCompat.MessagingStyle, מבצעים את הפעולות הבאות:

  • אפשר להתקשר למספר MessagingStyle.setConversationTitle() כדי לקבוע שם לצ'אטים קבוצתיים עם יותר משני אנשים. אפשר לבחור שם שיחה טוב, כמו שם הצ'אט הקבוצתי, או אם אין לו שם, רשימת המשתתפים בשיחה. בלי ההודעה הזו, יכול להיות שההודעה תיראה שייכת לשיחה אחד על אחד עם השולח של ההודעה האחרונה בשיחה.
  • משתמשים ב-method‏ MessagingStyle.setData() כדי לכלול הודעות מדיה כמו תמונות. המערכת תומכת בסוגי ה-MIME של התבנית image/*.

איך משתמשים בתכונה 'תשובה ישירה'

התכונה 'תשובה ישירה' מאפשרת למשתמש להשיב בתוך הודעה.

  • אחרי שמשתמש משיב את התגובה המוטבעת, צריך להשתמש ב-MessagingStyle.addMessage() כדי לעדכן את ההתראה MessagingStyle, ולא למשוך או לבטל את ההתראה. אם לא מבטלים את ההתראה, המשתמש יכול לשלוח כמה תשובות מההתראה.
  • כדי שפעולת התשובה בתוך השורה תתאים ל-Wear OS, צריך לקרוא ל-Action.WearableExtender.setHintDisplayInlineAction(true).
  • כדי לספק הקשר לשיחה עם תגובה ישירה, אפשר להוסיף להודעה היסטוריית הודעות באמצעות השיטה addHistoricMessage().

הפעלת התכונה 'תשובה מהירה'

  • כדי להפעיל את התשובה המהירה, קוראים לפונקציה setAllowGeneratedResponses(true). כך התשובות המהירות יהיו זמינות למשתמשים כשההתראה תעבור למכשיר עם Wear OS. התשובות של התכונה 'תשובות חכמות' נוצרות על ידי מודל למידת מכונה שפועל כל הזמן, על סמך ההקשר שמסופק על ידי ההתראה NotificationCompat.MessagingStyle. לא מתבצע העלאה של נתונים לאינטרנט כדי ליצור את התשובות.

הוספת מטא-נתונים של התראות