28 March 2020

Notification in Android ตอนที่ 6 - กำหนด Notification Style ในรูปแบบต่างๆ

Updated on

สำหรับในบทความนี้จะมาพูดถึงเรื่อง Notification Style เพื่อช่วยให้นักพัฒนาสามารถรังสรรค์ Notification ให้เหมาะสมกับการใช้งานตามความต้องการมากขึ้น

บทความในซีรีย์เดียวกัน

• Notification in Android ตอนที่ 1 - เรื่องพื้นฐานของ Notification ที่ควรรู้
• Notification in Android ตอนที่ 2 - คำสั่งพื้นฐานของ Notification
• Notification in Android ตอนที่ 3 - ทำให้ Notification สมบูรณ์ยิ่งขึ้น
• Notification in Android ตอนที่ 4 - Notification Action
• Notification in Android ตอนที่ 5 - Notification Channel
• Notification in Android ตอนที่ 6 - กำหนด Notification Style ในรูปแบบต่างๆ
• Notification in Android ตอนที่ 7 - การแจ้งเตือนแบบ Heads-up notification
• Notification in Android ตอนที่ 8 - อัปเดตข้อมูลให้กับ Notification

เพราะ Notification ไม่ได้มีไว้แค่ส่งข้อความเท่านั้น

ซึ่งนักพัฒนาสามารถประยุกต์ใช้งาน Notification ได้ตามใจชอบ และบ่อยครั้งก็จะพบว่า Notification ที่แสดงแต่ข้อความนั้นไม่สามารถตอบโจทย์ในการใช้งานบางอย่างได้

Notification บนแอนดรอยด์นั้นถูกออกแบบมาให้สามารถปรับเปลี่ยนรูปแบบในการแสดงผลได้ หรือที่เรียกว่า Notification Style

โดยที่แอนดรอยด์ได้เตรียมไว้บางส่วนให้แล้ว เรียกว่า System Template

Notification Style ในรูปแบบต่างๆ

ในบทความตอนแรกสุดของซีรีย์นี้ เจ้าของบล็อกได้กล่าวถึง Notification Style ที่จะช่วยให้นักพัฒนาแสดง Notification ในรูปแบบที่แตกต่างจากปกติได้ง่ายขึ้น ซึ่งจะมีทั้งหมด 7 แบบ

Standard Template - สำหรับการใช้งานทั่วๆไป
Big Text Template - สำหรับการแสดงข้อความหลายบรรทัด
Big Picture Template - สำหรับแสดงภาพขนาดใหญ่
Progress Template - สำหรับแสดงแถบ
Inbox Template - สำหรับแสดงข้อความหลายๆชุด
Messaging Template - สำหรับแสดงข้อความจากบทสนทนา
Media Template - สำหรับใช้ควบคุมการเล่นเพลงหรือวีดีโอ

ซึ่งทั้งหมดนี้เป็น Notification Style ที่มีอยู่แล้วในแอนดรอยด์ เพื่อให้นักพัฒนาสามารถเรียกใช้งานได้เลย


ในการใช้งานแต่ละ Style นั้นก็จะมีความแตกต่างกันออกไปตามบริบทของการใช้งาน รวมไปถึงคำสั่งที่มีให้เรียกใช้ด้วยเช่นกัน

การกำหนด Notification Style ลงใน Notification

ตอนกำหนดข้อมูลใน Builder เพื่อสร้างเป็น Notification จะมีคำสั่ง setStyle(...) อยู่ด้วย ซึ่งเป็นคำสั่งสำหรับกำหนด Notification Style

val notification = NotificationCompat.Builder(...).apply {
    ...
    setStyle(...)
}.build()

ซึ่งนักพัฒนาสามารถเรียก System Template เพื่อกำหนดลงใน Notification Style ได้เลย

Standard Style

เป็น Notification รูปแบบพื้นฐาน ซึ่งในบทความที่ผ่านมาทั้งหมดเป็นการสร้าง Notification ด้วย Standard Style นั่นเอง

val notification = NotificationCompat.Builder(...).apply {
    setSmallIcon(R.drawable.ic_notification)
    setContentTitle(title)
    setContentText(text)
}.build()

ดังนั้นจึงขอข้ามไปเลยนะ

Big Text Style

สำหรับ Notification ที่ต้องการแสดงข้อความหลายบรรทัด เหมาะกับการแจ้งเตือนที่มีรายละเอียดเป็นข้อความยาวๆ โดย Notification จะแสดงข้อมูลแค่บางส่วนก่อน และเมื่อผู้ใช้ขยาย Notification ก็จะแสดงข้อความทั้งหมด

ข้อมูลที่กำหนดไว้ใน Big Text Style จะแสดงก็ต่อเมื่อผู้ใช้ขยาย Notification เท่านั้น และเมื่อย่ออยู่ก็จะแสดงเป็น Standard Style แทน


ในการสร้าง Big Text Style จะใช้คลาส NotificationCompat.BigTextStyle และใช้คำสั่ง bigText(...) เพื่อกำหนดข้อความที่จะให้แสดงใน Big Text Style

val text: String = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setContentText(text)
    setStyle(NotificationCompat.BigTextStyle().bigText(text))
}.build()

เนื่องจากเป็นการแสดงสลับกันระหว่าง Standard Style กับ Big Text Style เพื่อให้การแสดงผลมีความต่อเนื่องกัน นักพัฒนาควรกำหนดข้อความลงในทั้ง 2 แบบให้เหมือนกัน

Big Picture Style

ถึงแม้ว่านักพัฒนาจะกำหนดภาพที่เรียกว่า Large Icon ให้กับ Notification ได้ก็จริง แต่ถึงกระนั้นก็ยังไม่เพียงพอสำหรับกรณีที่ต้องการแสดงภาพที่มีขนาดใหญ่ (อย่างเช่น ภาพถ่าย) ดังนั้นการใช้ Big Picture Style จะช่วยให้นักพัฒนาสามารถแสดงภาพประกอบเนื้อหาใน Notification ที่มีขนาดใหญ่ได้มากขึ้น


สำหรับวิธีการแสดงผลของ Big Picture Style จะคล้ายกับ Big Text Style ตรงที่จะแสดงเป็น Big Picture Style เฉพาะตอนที่ขยาย Notification เท่านั้น แต่ถ้าย่อไว้อยู่จะแสดงเป็น Standard Style แทน

ในการสร้าง Big Picture Style จะใช้คลาส NotificationCompat.BigPictureStyle และใช้คำสั่ง bigPicture(...) เพื่อกำหนดภาพที่ต้องการแสดง

val bigPicture: Bitmap = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setStyle(NotificationCompat.BigPictureStyle().bigPicture(bigPicture))
}.build()

โดยภาพที่กำหนดเป็น Big Picture จะต้องเป็นคลาส Bitmap เท่านั้น

นอกจากนี้นักพัฒนายังสามารถใส่ลูกเล่นให้กับการแสดงภาพได้ด้วยการกำหนดภาพที่ต้องการลงใน Large Icon และ Big Picture

val bigPicture: Bitmap = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setLargeIcon(bigPicture
    setStyle(NotificationCompat.BigPictureStyle()
            .bigPicture(bigPicture)
            .bigLargeIcon(null))
}.build()

จะเห็นว่าเจ้าของบล็อกได้กำหนดภาพในคำสั่ง bigLargeIcon(...) ให้เป็น Null ทั้งนี้ก็เพราะคำสั่งดังกล่าวจะทำให้ภาพ Large Icon หายไปตอนที่ขยาย Notification เพื่อแสดงเป็น Big Picture Style นั่นเอง



เพียงเท่านี้ผู้ใช้ก็จะเห็นภาพทั้งตอนย่อและขยาย Notification แล้ว

และการแสดง Notification แบบ Big Picture Style จะไม่เหมาะกับข้อความยาวๆ เพราะไม่สามารถแสดงข้อความทั้งหมดได้แบบ Big Text Style ดังนั้นนักพัฒนาควรระวังจุดนี้ไว้ให้ดี

Progress Style

เป็นการแสดง Notification แบบมีแถบ Progress เหมาะกับ Notification ที่ต้องการบอกให้ผู้ใช้รอ ในระหว่างที่แอปกำลังทำอะไรบางอย่างเป็นระยะเวลานาน เช่น ดาวน์โหลด/อัปโหลดไฟล์ เป็นต้น


ในการทำ Progress Style นั้น ไม่จำเป็นต้องกำหนด Style ใดๆลงไป แค่ใช้คำสั่ง setProgress(...) ซึ่งเป็นคำสั่งที่อยู่ในตอนกำหนดข้อมูลให้กับ Notification ตั้งแต่แรกแล้ว

val max = 100
val progress = 65
val indeterminate = false
val notification = NotificationCompat.Builder(...).apply {
    ...
    setProgress(max, progress, indeterminate)
}.build()

สำหรับค่าที่ต้องกำหนดให้กับ Progress ก็จะเหมือนกับ Progress Bar ทั่วไปเลย นักพัฒนาสามารถกำหนดค่า Max และค่า Progress ที่ต้องการได้ รวมไปถึงการแสดงแบบ Indeterminate

และ Content Title กับ Content Text จะถูกแสดงผลอยู่ในบรรทัดเดียวกัน โดย Content Title จะอยู่ชิดซ้าย และ Content Text จะอยู่ชิดขวา ดังนั้นการใช้ Progress Style จะต้องระวังไม่ให้ทั้ง 2 ข้อความยาวจนเกินไป

Inbox Style

Notification สำหรับข้อความที่มีหลายชุด ซึ่งต่างจาก Big Text Style ที่มีไว้แสดงข้อความชุดเดียว แต่มีข้อความยาวหลายบรรทัด แต่สำหรับ Inbox Style จะใช้แสดงข้อความที่มีหลายๆชุด โดยแต่ละชุดจะมีข้อความแค่บรรทัดเดียว


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

ซึ่งจะต่างจากการแสดง Notification แยกสินค้า ซึ่งโดยปกติแล้ว เมื่อผู้ใช้กดที่สินค้าใดๆก็จะเข้าไปที่รายละเอียดของสินค้านั้นๆโดยตรง


และในการแสดง Notification แบบ Inbox Style ก็จะแสดงเฉพาะตอนที่ขยาย Notification เท่านั้น แต่ถ้าย่ออยู่ก็จะแสดงเป็น Standard Style แทน

ในการสร้าง Inbox Style จะใช้คลาส NotificationCompat.InboxStyle โดยนักพัฒนาสามารถใส่ข้อความลงไปในนี้ด้วยคำสั่ง addLine(...) ซึ่งกำหนดได้สูงสุด 5 ข้อความด้วยกัน

val line1: CharSequence = ...
val line2: CharSequence = ...
val line3: CharSequence = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setStyle(NotificationCompat.InboxStyle()
            .addLine(line1)
            .addLine(line2)
            .addLine(line3)
    )
}.build()

และเนื่องจากเป็นการกำหนดข้อความหลายชุด ดังนั้นการใช้ Inbox Style ที่ดีควรกำหนด Content Text ให้สื่อกับเนื้อหาที่อยู่ในข้าง Inbox Style ด้วย เพื่อทำให้ผู้ใช้รู้สึกว่าอยากจะขยาย Notification เพื่อดูรายละเอียดของข้อความแต่ละชุด

val notification = NotificationCompat.Builder(...).apply {
    ...
    setContentTitle("You got 3 messages from your order status")
    setContentText("1 delivered and 2 shipped")
    setStyle(
        NotificationCompat.InboxStyle()
            .addLine(...)
            .addLine(...)
            .addLine(...)
    )
}.build()

หรือใช้วิธีกำหนด Summary Text เพื่อบอกให้ผู้ใช้รู้ว่ายังมีข้อมูลมากกว่านี้อีก เป็นการบอกผู้ใช้ให้กดที่ Notification เพื่อเข้าแอปไปดูข้อมูลทั้งหมดอีกวิธีหนึ่งเช่นกัน

val notification = NotificationCompat.Builder(...).apply {
    ...
    setStyle(
        NotificationCompat.InboxStyle()
            ...
            .setSummaryText("+4 more")
    )
}.build()


Messaging Style

Messaging Style ถูกออกแบบมาเหมาะสำหรับการแสดง Notification ในรูปแบบของบทสนทนา โดยที่นักพัฒนาไม่ต้องคิดถึงการแสดงข้อความยังไงถึงจะเหมาะสม

เพียงแค่ใช้ Messaging Style และกำหนดข้อมูลให้ตรงกับที่ Messaging Style ต้องการก็พอ แล้วข้อมูลดังกล่าวจะถูกนำไปแสดงให้อยู่ในรูปแบบของบทสนทนาทันที


ข้อดีีของการใช้ Messaging Style คือนักพัฒนาไม่ต้องกำหนด Content Title กับ Content Text เพราะในขณะที่ Notification กำลังย่ออยู่ ระบบจะดึงข้อความล่าสุดที่กำหนดไว้มาแสดงให้โดยอัตโนมัติ

ในการสร้าง Notification แบบ Messaging Style จะใช้คลาส NotificationCompat.MessagingStyle และใช้คำสั่ง addMessage(...) ในการกำหนดข้อความที่ต้องการแสดงให้ผู้ใช้เห็น

val person: Person = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setStyle(
        NotificationCompat.MessagingStyle(person)
            .addMessage(...)
            .addMessage(...)
            .addMessage(...)
    )
}.build()

การใช้งาน Messaging Style จะมีคลาสที่สำคัญอยู่ 2 คลาส ที่นักพัฒนาต้องใช้ นั่นก็คือคลาส Person และ Message

คลาส Person (androidx.core.app.Person)

สำหรับกำหนดข้อมูลของคนที่เป็นเจ้าของข้อความนั้นๆ ซึ่งจะประกอบไปด้วย

Name : ชื่อที่ใช้ในการแสดงผล
Icon : รูปประกอบสำหรับคนนั้นๆ
Bot : เป็นคนจริงๆหรือระบบอัตโนมัติ
Important : ความสำคัญของคนนั้นๆ
Key : Unique ID ของคนนั้นๆ ซึ่งมีประโยชน์ในกรณีที่ชื่อของคนนั้นใช้เป็น Unique ID ไม่ได้
URI : URI ของคนนั้นๆ จะใช้เป็นอีเมลหรือเบอร์ติดต่อก็ได้ โดยใช้ Schema เป็น mailto: หรือ tel: ไว้ข้างหน้า

val person: Person= Person.Builder().apply {
    setName("Akexorcist")
    setIcon(IconCompat.createWithBitmap(...))
    setBot(false)
    setImportant(true)
    setKey("0Dr1SvjKdMWqYeruln8u76mNbfo1")
    setUri("mailto:sleepingforless@example.com")
}.build()

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

คลาส Message (androidx.core.app.NotificationCompat.MessagingStyle.Message)

สำหรับกำหนดข้อความเพื่อแสดงใน Notification โดยจะต้องสร้าง 1 ข้อความต่อคลาส ซึ่งข้อมูลสำหรับคลาส Message จะประกอบไปด้วย

Text : ข้อความ
Timestamp : เวลาที่ส่งข้อความนั้นๆ​ โดยข้อความจะเรียงตามเวลาที่กำหนดไว้ที่นี่
Person : เจ้าของข้อความนั้นๆ

val text = "Why are you still reading this blog?"
val timestamp: Long = ...
val person: Person = ...
val message = NotificationCompat.MessagingStyle.Message(text, timestamp, person)

โดยคลาส Message จะใช้กำหนดข้อความลงใน Messaging Style อีกทีหนึ่ง แต่จริงๆนักพัฒนาไม่จำเป็นต้องสร้างคลาสนี้ก็ได้ เพราะการกำหนดข้อความลงใน Messaging Style สามารถกำหนดข้อมูลทั้ง 3 ตัวลงไปโดยตรงได้เลย

การแสดงบทสนทนาแบบ 1 ต่อ 1

ในการสร้าง Messaging Style สำหรับบทสนทนาแบบ 1 ต่อ 1 จะใช้คำสั่งลักษณะแบบนี้

val firstMessage: NotificationCompat.MessagingStyle.Message = ...
val secondMessage: NotificationCompat.MessagingStyle.Message = ...
val thirdMessage: NotificationCompat.MessagingStyle.Message = ...

val bitmap: Bitmap = ...
val person: Person = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setLargeIcon(bitmap)
    setStyle(
        NotificationCompat.MessagingStyle(person1)
            .addMessage(firstMessage)
            .addMessage(secondMessage)
            .addMessage(thirdMessage)
    )
}.build()

ซึ่งจริงๆแล้วนักพัฒนาสามารถกำหนด Message ลงไปตรงๆเลยก็ได้เช่นกัน จะได้ไม่ต้องสร้างคลาสแยกออกมาให้เสียเวลา

val text = "..."
val timestamp: Long = ...
val person: Person = ...
NotificationCompat.MessagingStyle(person1)
    ...
    .addMessage(text, timestamp, person)
    

และในการแสดงบทสนทนาแบบ 1 ต่อ 1 ควรกำหนดรูปของเจ้าของข้อความใน Large Icon ด้วย โดยใช้รูปเดียวกับที่กำหนดไว้ใน Person เพื่อให้ผู้ใช้รู้ได้ง่ายขึ้นว่าเป็นข้อความจากใคร


การแสดงบทสนทนาแบบกลุ่ม

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

val groupTitle: String = ...
val groupIcon: Bitmap = ...
val person1: Person = ...
val person2: Person = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setLargeIcon(groupIcon)
    setStyle(
        NotificationCompat.MessagingStyle(person2)
            .setConversationTitle(groupTitle)
            .setGroupConversation(true)
            .addMessage(/* message */ , /* timestamp */, person1)
            .addMessage(/* message */ , /* timestamp */, person1)
            .addMessage(/* message */ , /* timestamp */, person2)
            .addMessage(/* message */ , /* timestamp */, person2)
            .addMessage(/* message */ , /* timestamp */, person2)
    )
}.build()

โดยนักพัฒนาจะต้องกำหนด Conversation Title เพื่อให้ Notification แสดง Title เป็นชื่อกลุ่มสนทนาและกำหนด Group Conversation เพื่อให้ Notification รู้ว่าเป็นสนทนาแบบกลุ่ม เพียงเท่านี้ก็สามารถกำหนดข้อความแยกแต่ละคนได้แล้ว


การแสดงผลของ Person บน Android 9.0 Pie (API 28) กับเวอร์ชันที่เก่ากว่า

เนื่องจากคลาส Person เป็นคลาสที่เพิ่มเข้ามาใน Android 9.0 Pie (API 28) เพื่อให้นักพัฒนาสามารถกำหนดข้อมูลของบุคคลที่ต้องการได้ เช่น เจ้าของข้อความ, ผู้ส่งอีเมล หรือสมาชิกภายในกลุ่ม เป็นต้น

เดิมทีบนแอนดรอยด์เวอร์ชันเก่าๆจะกำหนดแค่ชื่อของบุคคลเท่านั้น ซึ่งใช้งานได้ไม่ค่อยยืดหยุ่นซักเท่าไร เช่น ไม่รองรับการแสดงภาพของบุคคลนั้นๆในตัว หรืออยากจะแนบ ID ของบุคคลนั้นๆก็ทำไม่ได้ ทำให้ทีมแอนดรอยด์สร้างคลาส Person ขึ้นมาเพื่อให้รองรับข้อมูลที่มากขึ้น และใส่ไว้ใน AndroidX เพื่อรองรับเวอร์ชันที่ต่ำกว่าด้วย


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

นอกจากนี้ Android 9.0 Pie (API 28) ได้เปลี่ยนมาแสดงเป็นภาพของคลาส Person จึงไม่แสดง Large Icon เพื่อไม่ให้เหลือพื้นที่น้อยเกินไป จึงเป็นที่มาว่าทำไมถึงแนะนำให้กำหนด Large Icon ไว้ด้วย เพื่อให้รองรับกับเวอร์ชันเก่านั่นเอง

Media Style

เป็น Notification Style ที่ออกแบบมาสำหรับแอปที่สามารถควบคุม Media Player ได้ (เล่นเพลงหรือวีดีโอ) และต้องการให้ผู้ใช้สามารถเห็นรายละเอียดและควบคุมการเล่นผ่าน Notification ได้นั่นเอง


ในการเรียกใช้งาน Media Style นั้นจะไม่สามารถเรียกใช้คลาส NotificationCompat ได้โดยตรง เพราะว่าทีมแอนดรอยด์ได้สร้างแยกออกมาเป็น Library อีกตัวหนึ่ง ดังนั้นนักพัฒนาจะต้องเพิ่มเข้าไปในโปรเจคดังนี้

implementation "androidx.media:media:1.1.0"

ซึ่งคลาส NotificationCompat สำหรับ Media Style จะเป็นกับที่ใช้ในการสร้าง Notification

// For create notification
androidx.core.app.NotificationCompat

// For Media Style
androidx.media.app.NotificationCompat

เพราะถึงแม้จะมีชื่อเหมือนกัน แต่ทั้งคู่ก็อยู่ใน Package คนละตัวกัน ดังนั้นควรระวังจุดนี้ไว้ให้ดี เพราะการสร้าง Media Style จะต้องเรียกใช้งานคลาสทั้ง 2 ตัวนี้พร้อมๆกัน และเจ้าของบล็อกจะใส่ Package แบบเต็มๆ สำหรับคลาส NotificationCompat ของ Media Style เท่านั้น

ในการใช้สร้าง Notification แบบ Media Style จะใช้คำสั่งลักษณะแบบนี้

val token: MediaSessionCompat.Token = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    setStyle(
        androidx.media.app.NotificationCompat.MediaStyle()
            .setMediaSession(token)
    )
}.build()

โดยคลาส MediaSessionCompat.Token เป็น Token จาก Session ที่ได้ในตอนที่นักพัฒนาสร้าง Media Player ขึ้นมา ซึ่งเจ้าของบล็อกจะไม่พูดถึงวิธีการสร้าง Media Player นะ

เพื่อให้การแสดงผลแบบ Media Style นั้นสมบูรณ์ นักพัฒนาจะต้องกำหนด Large Icon ด้วยภาพประกอบเพลงหรือวีดีโอ และ Action สำหรับควบคุมการทำงานของ Media Player สามารถกำหนด Action ได้สูงสุดถึง 5 Action ด้วยกัน


สำหรับ Pending Intent เพื่อใช้กำหนดใน Action แต่ละตัวสำหรับควบคุม Media Player สามารถเรียกจากคลาส MediaButtonReceiver ได้เลย ไม่ต้องสร้างขึ้นมาเอง

val context: Context = ...
val largeIcon: Bitmap = ...
val token: MediaSessionCompat.Token = ...
val previousAction = NotificationCompat.Action(R.drawable.ic_previous, "Previous", MediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS))
val pauseAction = NotificationCompat.Action(R.drawable.ic_pause, "Pause", MediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_PLAY_PAUSE))
val nextAction = NotificationCompat.Action(R.drawable.ic_next, "Next", MediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_SKIP_TO_NEXT))
val notification = NotificationCompat.Builder(...).apply {
    ...
    setLargeIcon(largeIcon)
    addAction(previousAction)
    addAction(pauseAction)
    addAction(nextAction)
    setStyle(
        androidx.media.app.NotificationCompat.MediaStyle()
            .setMediaSession(token)
    )
}.build()

สิ่งที่ต้องกำหนดให้กับ Action ก็จะเหลือแค่เพียงภาพและข้อความเท่านั้น

และเนื่องจาก Media Style สามารถแสดงผลได้ทั้งตอนย่อและขยาย Notification โดยเรียกการแสดงผลระหว่างที่ย่อ Notification อยู่ว่า Compact View

โดยนักพัฒนาจะต้องกำหนด Action ที่จะให้แสดงใน Compact View เอง เพราะว่าจะแสดงได้แค่ 3 Action เท่านั้น (จากเดิมได้ 5 Action) เนื่องจาก Action จะถูกย้ายไปอยู่แถวเดียวกับ Content Title และ Content Text

ในการกำหนด Action ที่จะแสดงใน Compact View จะต้องเพิ่มคำสั่ง setShowActionsInCompactView(...) เข้าไปในคลาส NotificationCompat.MediaStyle ดังนี้

val token: MediaSessionCompat.Token = ...
val notification = NotificationCompat.Builder(...).apply {
    ...
    addAction(...)
    addAction(...)
    addAction(...)
    setStyle(
        androidx.media.app.NotificationCompat.MediaStyle()
            .setMediaSession(token)
            .setShowActionsInCompactView(0, 1, 2)
    )
}.build()

คำสั่งดังกล่าวจะรับค่าเป็น Index ของ Action ที่ต้องการให้แสดงใน Compact View โดย Index ที่กำหนดจะต้องตรงกับจำนวน Action ที่กำหนดไว้ใน Notification ด้วย ไม่เช่นนั้นแอปจะพังเพราะ IndexOutOfBoundsException ทันทีที่แสดง Notification ตัวนี้

การแสดงผลของ Media Style จะแตกต่างกันไปในแต่ละเวอร์ชัน

เนื่องจาก Notification แบบ Media Style ก็เป็นอีกอย่างหนึ่งที่มีการปรับรูปแบบในการแสดงผลในทุกๆเวอร์ชัน 


แต่การใช้ Media Style จะไม่ต้องกังวลว่าจะต้องเขียนคำสั่งแยกเวอร์ชัน เพราะ Notification Compat จัดการให้หมดแล้วนั่นเอง

จบแล้ววววว ครบทุกแบบซะที เยอะเหลือเกิน

ถึงแม้ว่านักพัฒนาจะสามารถรังสรรค์รูปร่างหน้าตาของ Notification ได้ตามใจชอบด้วย Notification Style แต่ทีมแอนดรอยด์ก็ได้เตรียม System Template เพื่อให้นักพัฒนาสามารถนำไปใช้งานได้อย่างสะดวกสบาย ไม่ต้องมานั่งสร้างเองให้เสียเวลา ซึ่งครอบคลุมกับการใช้งานพื้นฐานของแอปส่วนใหญ่แล้วด้วย

ดังนั้นของดีแบบนี้ใช้เถอะ รับรองว่าไม่ผิดหวัง 😉