إنشاء إشعار

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

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

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

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

Groovy

dependencies {
    implementation "androidx.core:core-ktx:1.16.0"
}

Kotlin

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

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

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

الشكل 1. إشعار يتضمّن رمزًا وعنوانًا وبعض النص.

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

تضمين إذن التشغيل في بيان الأذونات

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

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

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

لمزيد من التفاصيل حول أذونات وقت التشغيل، يُرجى الاطّلاع على إذن وقت التشغيل للإشعارات.

ضبط محتوى الإشعار

للبدء، اضبط محتوى الإشعار والقناة باستخدام عنصر NotificationCompat.Builder يوضّح المثال التالي كيفية إنشاء إشعار يتضمّن ما يلي:

  • رمز صغير يتم ضبطه بواسطة setSmallIcon() هذا هو المحتوى الوحيد المرئي للمستخدم المطلوب.

  • عنوان تم ضبطه بواسطة setContentTitle()

  • النص الأساسي، الذي يتم ضبطه من خلال setContentText()

  • تم ضبط أولوية الإشعار من خلال setPriority(). تحدّد الأولوية مدى تطفّل الإشعار على الإصدار 7.1 من نظام التشغيل Android والإصدارات الأقدم. في نظام التشغيل 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 منك تقديم معرّف قناة. هذا الإعداد مطلوب للتوافق مع الإصدار 8.0 من نظام التشغيل Android (المستوى 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() لتوفير الدعم لنظام التشغيل 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()، الذي يزيل الإشعار تلقائيًا عندما ينقر عليه المستخدم.

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

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

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

لمزيد من المعلومات حول الطرق المختلفة لإعداد هدف الإشعار، راجِع مقالة بدء نشاط من إشعار.

عرض الإشعار

لإظهار الإشعار، استدعِ الدالة 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 (المستوى 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(). ومع ذلك، إذا كنت بصدد إنشاء تطبيق مراسلة، عليك إنشاء إشعار بنمط المراسلة وإلحاق الرسالة الجديدة بالمحادثة.

للحصول على مزيد من النصائح بشأن الإشعارات الواردة من تطبيقات المراسلة، راجِع القسم حول أفضل الممارسات لتطبيقات المراسلة.

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

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

عند ظهور الإشعار، يرى المستخدمون أحد الخيارَين التاليَين، وذلك حسب حالة قفل الجهاز:

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

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

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() كي يقطع إشعارك تسلسل عمل المستخدم، وذلك من خلال إصدار صوت أو اهتزاز أو تقديم إشارات مرئية، ولكن فقط عند ظهور الإشعار للمرة الأولى وليس عند ظهور التحديثات اللاحقة.

إزالة إشعار

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

  • يرفض المستخدم الإشعار.
  • ينقر المستخدم على الإشعار، إذا طلبت 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) لتجاوز وضع "عدم الإزعاج".