สร้างการแจ้งเตือน

การแจ้งเตือนจะให้ข้อมูลสั้นๆ ที่ทันท่วงทีเกี่ยวกับเหตุการณ์ในแอปขณะที่ไม่ได้ใช้งาน เอกสารนี้แสดงวิธีสร้างการแจ้งเตือนที่มีฟีเจอร์ต่างๆ ดูข้อมูลเบื้องต้นเกี่ยวกับลักษณะที่การแจ้งเตือนปรากฏใน Android ได้ที่ภาพรวมการแจ้งเตือน ดูโค้ดตัวอย่างที่ใช้การแจ้งเตือนได้ที่ SociaLite sample ใน GitHub

โค้ดในหน้านี้ใช้ API จากไลบรารี AndroidX ของ NotificationCompat API เหล่านี้ช่วยให้คุณเพิ่มฟีเจอร์ที่มีให้บริการใน Android เวอร์ชันใหม่เท่านั้นได้ ในขณะที่ยังคงเข้ากันได้กับ Android 9 (API ระดับ 28) อย่างไรก็ตาม ฟีเจอร์บางอย่าง เช่น การดําเนินการตอบกลับในบทสนทนา จะไม่ทํางานในเวอร์ชันเก่า

เพิ่ม AndroidX Core Library

แม้ว่าโปรเจ็กต์ส่วนใหญ่ที่สร้างด้วย 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 ของแอปจะปรากฏในข้อมูลโค้ดต่อไปนี้

<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 กำหนดให้คุณระบุรหัสช่อง การดำเนินการนี้จำเป็นสำหรับการเข้ากันได้กับ Android 8.0 (API ระดับ 26) ขึ้นไป แต่เวอร์ชันเก่าจะไม่สนใจ

โดยค่าเริ่มต้น ระบบจะตัดเนื้อหาข้อความของการแจ้งเตือนให้อยู่ภายใน 1 บรรทัด คุณสามารถแสดงข้อมูลเพิ่มเติมได้โดยการสร้างการแจ้งเตือนที่ขยายได้

รูปที่ 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 ขึ้นไป ให้เรียกใช้โค้ดนี้ทันทีที่แอปเริ่มทำงาน คุณเรียกใช้เมธอดนี้ซ้ำๆ ได้โดยไม่มีปัญหา เนื่องจากการสร้างแชแนลการแจ้งเตือนที่มีอยู่จะไม่ดําเนินการใดๆ

ตัวสร้าง NotificationChannel ต้องใช้ importance โดยใช้ค่าคงที่อย่างใดอย่างหนึ่งจากคลาส NotificationManager พารามิเตอร์นี้กำหนดวิธีขัดจังหวะผู้ใช้สำหรับการแจ้งเตือนที่อยู่ในช่องนี้ ตั้งค่า priority ด้วย setPriority() เพื่อรองรับ Android 7.1 และเวอร์ชันก่อนหน้า ดังที่แสดงในตัวอย่างก่อนหน้านี้

แม้ว่าคุณจะต้องตั้งค่าความสำคัญหรือลําดับความสําคัญของการแจ้งเตือนตามที่แสดงในตัวอย่างต่อไปนี้ แต่ระบบก็ไม่ได้รับประกันลักษณะการแจ้งเตือนที่คุณได้รับ ในบางกรณี ระบบอาจเปลี่ยนระดับความสำคัญตามปัจจัยอื่นๆ และผู้ใช้สามารถกำหนดระดับความสำคัญใหม่สำหรับช่องทางหนึ่งๆ ได้ทุกเมื่อ

อ่านเพิ่มเติมเกี่ยวกับความหมายของระดับต่างๆ ได้ที่หัวข้อระดับความสำคัญของการแจ้งเตือน

ตั้งค่าการดำเนินการด้วยการแตะของการแจ้งเตือน

การแจ้งเตือนทุกครั้งต้องตอบสนองต่อการแตะ โดยปกติแล้วเพื่อเปิดกิจกรรมในแอปที่สอดคล้องกับการแจ้งเตือน โดยระบุ Intent ของเนื้อหาที่กําหนดด้วยออบเจ็กต์ PendingIntent แล้วส่งไปยัง setContentIntent()

ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้าง Intent พื้นฐานเพื่อเปิดกิจกรรมเมื่อผู้ใช้แตะการแจ้งเตือน

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() ที่แสดงในตัวอย่างก่อนหน้านี้จะรักษาประสบการณ์การนําทางที่ผู้ใช้คาดหวังไว้หลังจากที่เปิดแอปโดยใช้การแจ้งเตือน คุณอาจต้องใช้แอตทริบิวต์นี้โดยขึ้นอยู่กับประเภทกิจกรรมที่คุณเริ่ม ซึ่งอาจเป็นกิจกรรมอย่างใดอย่างหนึ่งต่อไปนี้

  • กิจกรรมที่มีไว้สำหรับการตอบกลับการแจ้งเตือนเท่านั้น ผู้ใช้ไม่มีเหตุผลที่จะไปยังกิจกรรมนี้ในระหว่างการใช้งานแอปตามปกติ ดังนั้นกิจกรรมจึงเริ่มงานใหม่แทนที่จะเพิ่มลงในกองงานและกองที่มีอยู่ของแอป นี่คือประเภทของ Intent ที่สร้างขึ้นจากตัวอย่างก่อนหน้า

  • กิจกรรมที่มีอยู่ในขั้นตอนการทํางานปกติของแอป ในกรณีนี้ การเริ่มกิจกรรมจะสร้างกองซ้อนย้อนกลับเพื่อให้ผู้ใช้ใช้ปุ่มย้อนกลับและปุ่มขึ้นได้ตามปกติ

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีต่างๆ ในการกำหนดค่า Intent ของการแจ้งเตือนได้ที่หัวข้อเริ่มกิจกรรมจากการแจ้งเตือน

แสดงการแจ้งเตือน

หากต้องการให้การแจ้งเตือนปรากฏ ให้เรียกใช้ 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 ปุ่ม ซึ่งช่วยให้ผู้ใช้ตอบกลับได้อย่างรวดเร็ว เช่น เลื่อนการช่วยเตือนหรือตอบกลับ SMS แต่ปุ่มดำเนินการเหล่านี้ต้องไม่ทำซ้ำการดำเนินการที่ดำเนินการเมื่อผู้ใช้แตะการแจ้งเตือน

รูปที่ 3 การแจ้งเตือนที่มีปุ่มการทำงาน 1 ปุ่ม

หากต้องการเพิ่มปุ่มดำเนินการ ให้ส่ง 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) ช่วยให้ผู้ใช้ป้อนข้อความในการแจ้งเตือนได้โดยตรง จากนั้นระบบจะนำส่งข้อความไปยังแอปของคุณโดยไม่ต้องเปิดกิจกรรม เช่น คุณสามารถใช้การดำเนินการตอบกลับโดยตรงเพื่อให้ผู้ใช้ตอบกลับ SMS หรืออัปเดตรายการงานจากภายในการแจ้งเตือนได้

รูปที่ 4 การแตะปุ่ม "ตอบ" จะเปิดกล่องป้อนข้อความ

การดําเนินการตอบกลับโดยตรงจะปรากฏเป็นปุ่มเพิ่มเติมในการแจ้งเตือนที่จะเปิดกล่องป้อนข้อความ เมื่อผู้ใช้พิมพ์เสร็จแล้ว ระบบจะแนบคำตอบแบบข้อความไปยัง Intent ที่คุณระบุไว้สำหรับการดำเนินการแจ้งเตือน และส่ง Intent ไปยังแอป

เพิ่มปุ่มตอบกลับ

หากต้องการสร้างการดำเนินการที่มีการแจ้งเตือนซึ่งรองรับการตอบกลับโดยตรง ให้ทำตามขั้นตอนต่อไปนี้

  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

ดึงข้อมูลป้อนจากผู้ใช้จากการตอบกลับ

หากต้องการรับอินพุตของผู้ใช้จาก UI การตอบกลับของการแจ้งเตือน ให้เรียกใช้ 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() ด้วยรหัสและแท็กเดียวกัน (หากมี) ซึ่งจำเป็นต้องใช้เพื่อซ่อน UI การตอบกลับโดยตรงและยืนยันกับผู้ใช้ว่าระบบได้รับและประมวลผลการตอบกลับแล้ว

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

ระบบจะใช้ข้อมูลนี้เกี่ยวกับหมวดหมู่การแจ้งเตือนเพื่อตัดสินใจว่าจะแสดงการแจ้งเตือนเมื่ออุปกรณ์อยู่ในโหมดห้ามรบกวนหรือไม่ อย่างไรก็ตาม คุณไม่จำเป็นต้องตั้งค่าหมวดหมู่สำหรับทั้งระบบ โปรดดำเนินการดังกล่าวก็ต่อเมื่อการแจ้งเตือนตรงกับหมวดหมู่ใดหมวดหมู่หนึ่งที่กำหนดโดย in NotificationCompat

แสดงข้อความด่วน

แอปของคุณอาจต้องแสดงข้อความที่เร่งด่วนและเกี่ยวข้องกับเวลา เช่น สายเรียกเข้าหรือการปลุกที่ดัง ในกรณีเหล่านี้ คุณสามารถเชื่อมโยง Intent แบบเต็มหน้าจอกับการแจ้งเตือนได้

เมื่อเรียกใช้การแจ้งเตือน ผู้ใช้จะเห็นข้อความอย่างใดอย่างหนึ่งต่อไปนี้ ทั้งนี้ขึ้นอยู่กับสถานะการล็อกของอุปกรณ์

  • หากอุปกรณ์ของผู้ใช้ล็อกอยู่ กิจกรรมแบบเต็มหน้าจอจะปรากฏขึ้นโดยครอบคลุมหน้าจอล็อก
  • หากอุปกรณ์ของผู้ใช้ไม่ได้ล็อกอยู่ การแจ้งเตือนจะปรากฏในรูปแบบที่ขยายซึ่งมีตัวเลือกสำหรับจัดการหรือปิดการแจ้งเตือน

ข้อมูลโค้ดต่อไปนี้แสดงวิธีเชื่อมโยงการแจ้งเตือนกับ Intent แบบเต็มหน้าจอ

Kotlin

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

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

Java

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

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

ตั้งค่าระดับการมองเห็นหน้าจอล็อก

หากต้องการควบคุมระดับรายละเอียดที่แสดงในการแจ้งเตือนจากหน้าจอล็อก ให้เรียกใช้ setVisibility() แล้วระบุค่าใดค่าหนึ่งต่อไปนี้

  • VISIBILITY_PUBLIC: เนื้อหาทั้งหมดของการแจ้งเตือนจะแสดงบนหน้าจอล็อก

  • VISIBILITY_SECRET: ไม่มีการแจ้งเตือนใดๆ แสดงบนหน้าจอล็อก

  • VISIBILITY_PRIVATE: มีเฉพาะข้อมูลพื้นฐาน เช่น ไอคอนการแจ้งเตือนและชื่อเนื้อหา ที่แสดงบนหน้าจอล็อก เนื้อหาทั้งหมดของการแจ้งเตือนไม่แสดง

เมื่อตั้งค่า VISIBILITY_PRIVATE คุณจะระบุเนื้อหาการแจ้งเตือนเวอร์ชันอื่นที่ซ่อนรายละเอียดบางอย่างได้ด้วย เช่น แอป SMS อาจแสดงการแจ้งเตือนที่ระบุว่า "คุณมี SMS ใหม่ 3 ข้อความ" แต่ซ่อนเนื้อหาข้อความและผู้ส่ง หากต้องการระบุการแจ้งเตือนทางเลือกนี้ ให้สร้างการแจ้งเตือนทางเลือกด้วย NotificationCompat.Builder ตามปกติก่อน จากนั้นแนบการแจ้งเตือนทางเลือกมากับการแจ้งเตือนปกติด้วย setPublicVersion()

โปรดทราบว่าผู้ใช้มีสิทธิ์ควบคุมขั้นสูงสุดเสมอว่าจะให้แสดงการแจ้งเตือนบนหน้าจอล็อกหรือไม่ และสามารถควบคุมการแจ้งเตือนตามช่องทางการแจ้งเตือนของแอป

อัปเดตการแจ้งเตือน

หากต้องการอัปเดตการแจ้งเตือนหลังจากที่ออกแล้ว ให้เรียกใช้ NotificationManagerCompat.notify() อีกครั้งโดยส่งรหัสเดียวกับที่ใช้ก่อนหน้านี้ หากปิดการแจ้งเตือนก่อนหน้า ระบบจะสร้างการแจ้งเตือนใหม่แทน

คุณอาจเรียกใช้ setOnlyAlertOnce() เพื่อให้การแจ้งเตือนรบกวนผู้ใช้ด้วยเสียง การสั่น หรือสิ่งบอกใบ้ที่เป็นภาพได้เฉพาะเมื่อการแจ้งเตือนปรากฏขึ้นเป็นครั้งแรกเท่านั้น และจะไม่แสดงเมื่อมีการอัปเดตในภายหลัง

นำการแจ้งเตือนออก

การแจ้งเตือนจะยังคงปรากฏให้เห็นจนกว่าจะเกิดเหตุการณ์อย่างใดอย่างหนึ่งต่อไปนี้

  • ผู้ใช้ปิดการแจ้งเตือน
  • ผู้ใช้แตะการแจ้งเตือนหากคุณเรียกใช้ setAutoCancel() เมื่อสร้างการแจ้งเตือน
  • คุณเรียกใช้ cancel() เพื่อดูรหัสการแจ้งเตือนที่เฉพาะเจาะจง วิธีนี้จะลบการแจ้งเตือนที่ดำเนินอยู่ด้วย
  • คุณเรียกใช้ cancelAll() ซึ่งจะนำการแจ้งเตือนทั้งหมดที่คุณเคยออกไว้ออก
  • ระยะเวลาที่ระบุจะสิ้นสุดลงหากคุณตั้งค่าการหมดเวลาเมื่อสร้างการแจ้งเตือนโดยใช้ setTimeoutAfter() หากจำเป็น คุณสามารถยกเลิกการแจ้งเตือนก่อนที่ระยะเวลาหมดเวลาที่กำหนดไว้จะสิ้นสุดลง

แนวทางปฏิบัติแนะนำสำหรับแอปรับส่งข้อความ

โปรดพิจารณาแนวทางปฏิบัติแนะนำที่ระบุไว้ที่นี่เมื่อสร้างการแจ้งเตือนสำหรับแอปรับส่งข้อความและแอปแชท

ใช้ MessagingStyle

ตั้งแต่ Android 7.0 (API ระดับ 24) เป็นต้นไป Android มีเทมเพลตสไตล์การแจ้งเตือนสำหรับเนื้อหาการรับส่งข้อความโดยเฉพาะ เมื่อใช้คลาส NotificationCompat.MessagingStyle คุณจะสามารถเปลี่ยนป้ายกำกับหลายรายการที่แสดงในการแจ้งเตือน ซึ่งรวมถึงชื่อการสนทนา ข้อความเพิ่มเติม และมุมมองเนื้อหาสําหรับการแจ้งเตือน

ข้อมูลโค้ดต่อไปนี้แสดงวิธีปรับแต่งสไตล์ของข้อความแจ้งโดยใช้คลาส MessagingStyle

Kotlin

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

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

Java

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

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

ตั้งแต่ Android 9.0 (API ระดับ 28) เป็นต้นไป คุณต้องใช้คลาส Person ด้วยเพื่อให้ได้การแสดงผลการแจ้งเตือนและรูปโปรไฟล์ที่ดีที่สุด

เมื่อใช้ NotificationCompat.MessagingStyle ให้ทําดังนี้

  • โทรไปที่ MessagingStyle.setConversationTitle() เพื่อตั้งชื่อแชทกลุ่มที่มีสมาชิกมากกว่า 2 คน ชื่อการสนทนาที่ดีอาจเป็นชื่อของแชทกลุ่ม หรือหากไม่มีชื่อ ให้ใช้รายชื่อผู้เข้าร่วมการสนทนา หากไม่มีข้อความนี้ ระบบอาจเข้าใจผิดว่าข้อความดังกล่าวเป็นส่วนหนึ่งของการสนทนาแบบตัวต่อตัวกับผู้ส่งข้อความล่าสุดในการสนทนา
  • ใช้วิธี 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) เพื่อลบล้างโหมดห้ามรบกวน