إنشاء إشعار

تقدِّم الإشعارات معلومات قصيرة في الوقت المناسب عن الأحداث في تطبيقك عندما يكون غير قيد الاستخدام. يوضّح لك هذا المستند كيفية إنشاء إشعار يحتوي على ميزات مختلفة. للحصول على مقدّمة عن كيفية ظهور الإشعارات على Android، اطّلِع على نظرة عامة على الإشعارات. للحصول على نموذج رمز يستخدم الإشعارات، اطّلِع على نموذج SociaLite على GitHub.

تستخدِم الرموز البرمجية في هذه الصفحة واجهات برمجة التطبيقات NotificationCompat من مكتبة AndroidX. تتيح لك واجهات برمجة التطبيقات هذه إضافة ميزات متاحة فقط على الإصدارات الأحدث من Android مع الحفاظ على التوافق مع الإصدار 9 من Android (المستوى 28 لواجهة برمجة التطبيقات). ومع ذلك، فإنّ بعض الميزات، مثل إجراء الردّ المضمّن، لا تعمل في الإصدارات السابقة.

إضافة مكتبة AndroidX Core

على الرغم من أنّ معظم المشاريع التي تم إنشاؤها باستخدام "استوديو Android" تتضمّن التبعيات اللازمة لاستخدام NotificationCompat، تأكَّد من أنّ ملف build.gradle على مستوى الوحدة يتضمّن التبعية التالية:

رائع

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

Kotlin

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

إنشاء إشعار أساسي

يعرض الإشعار في أبسط وأصغر شكل له، والذي يُعرف أيضًا باسم الشكل المُدمَج، رمزًا وعنوانًا وكمية صغيرة من المحتوى النصي. يوضّح هذا القسم كيفية إنشاء إشعار يمكن للمستخدم النقر عليه لبدء نشاط في تطبيقك.

الشكل 1: إشعار يحتوي على رمز وعنوان وبعض النصوص

لمزيد من التفاصيل حول كل جزء من الإشعار، اطّلِع على مكونات الإشعار.

الإفصاح عن إذن التشغيل

يتيح نظام التشغيل Android 13 (المستوى 33 لواجهة برمجة التطبيقات) والإصدارات الأحدث إذن التشغيل لنشر إشعارات غير المعفاة (بما في ذلك الخدمات التي تعمل في المقدّمة) من تطبيق.

يظهر الإذن الذي يجب الإفصاح عنه في ملف بيان تطبيقك في مقتطف الرمز التالي:

<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);

يتطلب مُنشئ NotificationCompat.Builder تقديم معرّف channel. هذا الإجراء مطلوب للتوافق مع Android 8.0 (المستوى 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);

لمزيد من المعلومات عن أنماط الإشعارات الكبيرة الأخرى، بما في ذلك كيفية إضافة صورة وعناصر تحكّم في تشغيل الوسائط، يُرجى الاطّلاع على مقالة إنشاء إعلام قابل للتوسيع.

إنشاء قناة وضبط أهميتها

لكي تتمكّن من إرسال الإشعار على الإصدار 8.0 من نظام التشغيل Android والإصدارات الأحدث، عليك تسجيل قناة الإشعارات في النظام من خلال تمرير مثيل 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);
    }
}

وبما أنّه يجب إنشاء قناة الإشعارات قبل نشر أي إشعارات على الإصدار 8.0 من Android والإصدارات الأحدث، عليك تنفيذ هذا الرمز البرمجي فور بدء تطبيقك. من الآمن استدعاء هذه الوظيفة بشكل متكرّر، لأنّ إنشاء قناة إعلام حالية لا يؤدي إلى تنفيذ أيّ عملية.

تتطلّب الدالة الإنشائية NotificationChannel استخدام importance، وذلك باستخدام أحد الثوابت من فئة NotificationManager. تحدِّد هذه القيمة كيفية مقاطعة المستخدم بشأن أي إشعار ينتمي إلى هذه القناة. اضبط الأولوية باستخدام setPriority() لتتوافق مع الإصدار 7.1 من نظام Android والإصدارات الأقدم، كما هو موضّح في المثال السابق.

على الرغم من أنّه عليك ضبط أهمية الإشعار أو أولويته كما هو موضّح في المثال التالي، لا يضمن النظام سلوك التنبيه الذي تحصل عليه. في بعض الحالات، قد يغيّر النظام مستوى الأهمية استنادًا إلى عوامل أخرى، ويمكن للمستخدم في أي وقت إعادة تحديد مستوى الأهمية لقناة معيّنة.

لمزيد من المعلومات عن معنى المستويات المختلفة، يمكنك الاطّلاع على مقالة مستويات أهمية الإشعارات.

ضبط إجراء النقر على الإشعار

يجب أن يستجيب كل إشعار للنقر عليه، وعادةً ما يكون ذلك لفتح نشاط في تطبيقك يتوافق مع الإشعار. لإجراء ذلك، حدِّد نية محتوى يتم تحديدها باستخدام عنصر 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 لتشغيل مهمة في background ، يُرجى الاطّلاع على نظرة عامة على "البثّ".

إذا كنت تحاول بدلاً من ذلك إنشاء إشعار يتضمّن أزرار تشغيل الوسائط، مثل الإيقاف المؤقت للمقاطع الصوتية وتخطّيها، يمكنك الاطّلاع على كيفية إنشاء إشعار يتضمّن عناصر التحكّم في الوسائط.

إضافة إجراء ردّ مباشر

يتيح إجراء الرد المباشر، الذي تم طرحه في Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات)، للمستخدمين إدخال نص مباشرةً في الإشعار. ويتم بعد ذلك إرسال النص إلى تطبيقك بدون فتح نشاط. على سبيل المثال، يمكنك استخدام إجراء ردّ مباشر للسماح للمستخدمين بالردّ على الرسائل النصية أو تعديل قوائم المهام من داخل الإشعار.

الشكل 4: يؤدي النقر على زر "رد" إلى فتح إدخال النص.

يظهر إجراء الرد المباشر كزر إضافي في الإشعار الذي يفتح حقل إدخال نص. عندما ينتهي المستخدم من الكتابة، يُرفِق النظام الردّ النصي بالنية التي تحدّدها للإجراء المرتبط بالإشعار ويُرسِل النيّة إلى تطبيقك.

إضافة زر الردّ

لإنشاء إجراء إشعار يتيح الردّ المباشر، اتّبِع الخطوات التالية:

  1. أنشئ مثيلًا من RemoteInput.Builder يمكنك إضافته إلى إجراء الإشعار. يقبل أسلوب الإنشاء لهذه الفئة سلسلة يستخدمها النظام كمفتاح لإدخال النص. يستخدم تطبيقك هذا المفتاح لاحقًا لاسترداد نص الإدخال.

    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: شريط التقدّم أثناء العملية

إذا كان بإمكانك تقدير نسبة اكتمال العملية في أي وقت، استخدِم شكل التحديد "determinate" للمؤشر، كما هو موضّح في الشكل 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.

عرض رسالة عاجلة

قد يحتاج تطبيقك إلى عرض رسالة عاجلة حسّاسة للوقت، مثل مكالمة هاتفية واردة أو منبّه يرنّ. في هذه الحالات، يمكنك ربط نية عرض التطبيق على الشاشة الكاملة بإشعارك.

عند تشغيل الإشعار، تظهر للمستخدمين إحدى الحالتَين التاليتَين، استنادًا إلى حالة قفل الجهاز:

  • إذا كان جهاز المستخدم مقفلاً، يظهر نشاط بملء الشاشة يغطي شاشة القفل.
  • إذا كان جهاز المستخدم غير مقفل، يظهر الإشعار في شكل موسّع يتضمّن خيارات للتعامل مع الإشعار أو إغلاقه.

يوضّح المقتطف البرمجي التالي كيفية ربط إشعارك بمحاولة عرض بملء الشاشة:

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، يمكنك أيضًا تقديم نسخة بديلة من محتوى الإشعار الذي يخفي تفاصيل معيّنة. على سبيل المثال، قد يعرض تطبيق الرسائل القصيرة إشعارًا يفيد بأنّه "لديّك 3 رسائل نصية جديدة"، ولكنه يخفي محتوى الرسائل ومُرسِليها. لتقديم هذا البديل للإشعار، عليك أولاً إنشاء الإشعار البديل باستخدام NotificationCompat.Builder كالمعتاد. بعد ذلك، اربط الإشعار البديل بالإشعار العادي باستخدام setPublicVersion().

يُرجى العِلم أنّ المستخدم يتحكّم دائمًا في ما إذا كانت الإشعارات تظهر على شاشة القفل، ويمكنه التحكّم فيها استنادًا إلى قنوات الإشعارات في تطبيقك.

تعديل إشعار

لتعديل إشعار بعد إصداره، يُرجى الاتصال برقم NotificationManagerCompat.notify() مرة أخرى وإرسال المعرّف نفسه الذي استخدمته في السابق. في حال إغلاق الإشعار السابق، سيتم إنشاء إشعار جديد بدلاً منه.

يمكنك اختياريًا استخدام القيمة setOnlyAlertOnce() لإشعار المستخدم من خلال الصوت أو الاهتزاز أو إشارات visually فقط في المرة الأولى التي يظهر فيها الإشعار وليس في التحديثات اللاحقة.

إزالة إشعار

تظل الإشعارات مرئية إلى أن يحدث أحد الإجراءَين التاليَين:

  • يرفض المستخدم الإشعار.
  • ينقر المستخدم على الإشعار، إذا كنت تستدعي setAutoCancel() عند إنشاء الإشعار.
  • يمكنك الاتصال بـ cancel() لطلب معرّف إشعار محدّد. تؤدي هذه الطريقة أيضًا إلى حذف الرسائل الإشعارية الجارية.
  • يمكنك الاتصال بـ cancelAll()، لإزالة جميع الإشعارات التي أصدرتَها سابقًا.
  • تنتهي المدة المحدّدة إذا ضبطت مهلة عند إنشاء الإشعار باستخدام setTimeoutAfter(). يمكنك إلغاء إشعار قبل انقضاء مهلة الانتظار المحدّدة.

أفضل الممارسات المتعلّقة بتطبيقات المراسلة

وننصحك باتّباع أفضل الممارسات الواردة هنا عند إنشاء إشعارات لتطبيقات الرسائل والمحادثات.

استخدام MessagingStyle

بدءًا من الإصدار 7.0 من نظام Android (المستوى 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();

بدءًا من الإصدار 9.0 من Android (المستوى 28 لواجهة برمجة التطبيقات)، يجب أيضًا استخدام فئة Person للحصول على عرض مثالي للإشعارات وصور المستخدمين الرمزية.

عند استخدام NotificationCompat.MessagingStyle، اتّبِع الخطوات التالية:

  • اضغط على رمز المكالمة MessagingStyle.setConversationTitle() لتحديد عنوان للمحادثات الجماعية التي تضم أكثر من شخصَين. قد يكون عنوان المحادثة الجيد هو اسم المحادثة الجماعية أو قائمة بالمشاركين في المحادثة إذا لم يكن لها اسم. بدون ذلك، قد يتم الخلط بين الرسالة وبين رسالة محادثة بين شخصين مع مرسل آخر رسالة في المحادثة.
  • استخدِم الطريقة MessagingStyle.setData() لتضمين رسائل وسائط، مثل الصور. تكون أنواع MIME للنموذج image/* متوافقة.

استخدام ميزة "الرد المباشر"

يتيح الرد المباشر للمستخدم الردّ بشكل مضمّن على رسالة.

  • بعد أن يردّ المستخدم باستخدام إجراء الردّ المضمّن، استخدِم MessagingStyle.addMessage() لتعديل الإشعار MessagingStyle، ولا تتراجع عن الإشعار أو تلغيه. يتيح عدم إلغاء الإشعار للمستخدم إرسال عدة ردود من الإشعار.
  • لجعل إجراء الردّ المضمّن متوافقًا مع نظام التشغيل Wear OS، اتصل بالرقم Action.WearableExtender.setHintDisplayInlineAction(true).
  • استخدِم رمز addHistoricMessage() لتوفير سياق لمحادثة ردّ مباشر من خلال إضافة رسائل سابقة إلى الإشعار.

تفعيل ميزة "الرد السريع"

  • لتفعيل ميزة "الرد السريع"، اضغط على رمز setAllowGeneratedResponses(true) إجراء الرد. يؤدي ذلك إلى توفّر الردود السريعة للمستخدمين عند ربط الإشعار بجهاز Wear OS. يتم إنشاء ردود "الرد الذكي" باستخدام نموذج تعلُّم آلة مُشغَّل بالكامل على الساعة باستخدام السياق الذي يقدّمه NotificationCompat.MessagingStyle الإشعار، ولا يتم تحميل أي بيانات إلى الإنترنت لإنشاء ردود.

إضافة بيانات وصفية للإشعار

  • يمكنك تحديد البيانات الوصفية للإشعارات لإعلام النظام بكيفية التعامل مع إشعارات التطبيق عندما يكون الجهاز في وضع Do Not Disturb mode. على سبيل المثال، استخدِم الرمز addPerson() أو setCategory(Notification.CATEGORY_MESSAGE) لإيقاف وضع "عدم الإزعاج".