יצירת התראה

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

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

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

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

Groovy

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 במסך מלא:

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

החל מגרסה 7.0 של Android (רמת 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. לא מתבצע העלאה של נתונים לאינטרנט כדי ליצור את התשובות.

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