Notification in Android ตอนที่ 2 — คำสั่งพื้นฐานของ Notification

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

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

เรื่องราวในบทความนี้

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

โดยการสร้าง Notification แบบที่ง่ายที่สุดจะประกอบไปด้วย

เตรียม Notification Channel และ​ Notification Channel Group

Notification Channel และ Notification Channel Group เป็นสิ่งที่เพิ่มเข้ามาใน Android 8.0 Oreo (API 26) ขึ้นไป โดยบังคับให้นักพัฒนาต้องสร้าง Channel ขึ้นมาสำหรับ Notification ทุกตัวที่จะแสดงในแอป

ถ้ามี Channel จำนวนเยอะมาก และอยากจะแบ่งกลุ่มให้กับ Channel ก็ให้สร้าง Channel Group (สามารถสร้าง Channel ที่ไม่มี Channel Group ได้)

โดยคำสั่งที่ใช้ในการสร้าง Channel จะมีลักษณะแบบนี้

fun initNotificationChannel(context: Context) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val id = "new_promotion"
        val name = "New Promotion"
        val importance = NotificationManager.IMPORTANCE_HIGH
        val channel = NotificationChannel(id, name, importance)
        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        manager.createNotificationChannel(channel)
    }
}

ซึ่งประกอบไปด้วย Channel ID, Channel Name และ Importance

Channel ID

ID ของ Channel โดยห้ามซ้ำกับ Channel ตัวอื่นที่อยู่ในแอปเดียวกัน

Channel Name

ชื่อของ Channel ที่ใช้แสดงให้ผู้ใช้เห็นที่หน้าเมนู Notification ของ App Info

Importance

ระดับความสำคัญของ Notification ที่อยู่ใน Channel นี้ ซึ่งจะมีผลต่อเงื่อนไขในการแสดงผลของ Notification ซึ่งระบแอนดรอยด์จะใช้แทนการกำหนด Priority ของ Notification ในเวอร์ชันเก่า

คำสั่งนี้ใช้เฉพาะ Android 8.0 Oreo (API 26) ขึ้นไปเท่านั้น

เนื่องจากคำสั่งดังกล่าวถูกเพิ่มเข้ามาตั้งแต่ Android 8.0 Oreo (API 26) ถ้าแอปรองรับเวอร์ชันที่ต่ำกว่านั้นจะต้องเช็คเวอร์ชันแอนดรอยด์ของเครื่องที่เรียกใช้งานแอปด้วยเสมอ

ในกรณีที่ต้องการสร้าง Channel Group ด้วยก็จะต้องเพิ่มคำสั่งเข้ามาแบบนี้

fun initNotificationChannel(context: Context) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val groupId = "announcement"
        val groupName = "Announcement"
        val group = NotificationChannelGroup(groupId, groupName)

        val channelId = "new_promotion"
        val channelName = "New Promotion"
        val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
        channel.group = groupId

        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        manager.createNotificationChannelGroup(group)
        manager.createNotificationChannel(channel)
    }
}

การสร้าง Channel Group ก็จะคล้ายกับการสร้าง Channel ที่ต้องกำหนดชื่อและ ID ให้กับ Channel Group ด้วย และต้องกำหนด Channel Group ให้กับ Channel โดยใช้ ID ของ Channel Group ด้วย

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

เพียงเท่านี้ก็จะทำให้แอปมี Channel และ Channel Group แล้ว โดยสามารถเช็คได้จากหน้าเมนู Notification ใน App Info

ควรสร้าง Notification Channel และ Notification Channel Group ตอนไหน?

แนะนำให้สร้างแค่ตอนเปิดแอปครั้งแรกเท่านั้นก็พอ เพราะว่าเมื่อทำการสร้างขึ้นมาแล้ว ก็จะอยู่ติดแอปตลอดไป จนกว่าจะลบแอป (Uninstall) หรือลบข้อมูลในแอป (Clear Data)

เพราะว่าสร้างแค่ครั้งเดียวก็พอ นักพัฒนาจึงใส่คำสั่งนี้ไว้ในคลาส Application เลย เพื่อให้ทำการสร้างทันทีที่เปิดแอปขึ้นมา

// AwesomeApplication.kt
class AwesomeApplication : Application() {
    override fun onCreate() {
        /* ... */
        initNotificationChannel(applicationContext)
    }

    private fun initNotificationChannel(context: Context) {
        /* ... */
    }
}

โดย Channel และ Channel Group สามารถสร้างทับของเดิมได้ ไม่มีปัญหาอะไร ดังนั้นนักพัฒนาส่วนใหญ่ก็จะไม่สนว่ามันจะถูกสร้างซ้ำอีกครั้งในตอนที่คลาส Application ถูกสร้างขึ้น

ถ้าอยากรู้เรื่องราวของ Channel และ Channel Group มากกว่านี้ก็เข้าไปอ่านกันได้ที่ Notification in Android ตอนที่ 5 - Notification Channel

Notification in Android ตอนที่ 5 — Notification Channel
ในบทความนี้เจ้าของบล็อกจะมาพูดรายละเอียดและการทำงานของ Notification Channel ที่เป็น 1 ในสิ่งที่นักพัฒนาต้องใส่ทุกครั้งเพื่อให้ Notification ทำงานได้บนแอนดรอยด์เวอร์ชันใหม่ๆกัน

ต่อไปก็…

สร้างข้อมูลที่ต้องใช้ในการแสดง Notification

ข้อมูลที่จำเป็นต้องมีใน Notification จะมีอยู่ 5 อย่างด้วยกัน คือ Context, Channel ID, Small Icon, Content Title และ Content Text

val context: Context = /* ... */
val channelId = "new_promotion"
val title = "Are you looking for awesome Android article?"
val text = "Why don't you look at Sleeping For Less website. There's a lot of interest article about Android application development."
val notification = NotificationCompat.Builder(context, channelId).apply {
    setSmallIcon(R.drawable.ic_notification)
    setContentTitle(title)
    setContentText(text)
}.build()

Channel ID

จะเป็นต้องเป็น ID ของ Notification Channel ที่เคยสร้างไว้แล้ว ถ้าเป็น Channel ID ไม่เคยถูกสร้างขึ้นมาก่อนก็จะทำให้แอปพังทันที

Small Icon

สำหรับกำหนด Drawable Resource เพื่อแสดงเป็นภาพไอคอนตอนแสดง Notification

Content Title

สำหรับกำหนดชื่อหัวข้อของ Notification นั้นๆ เพื่อให้ผู้ใช้รู้ว่าเป็น Notification ในเรื่องอะไร

Content Text

สำหรับกำหนดรายละเอียดของ Notification เพื่อให้ผู้ใช้เห็นเนื้อหาจาก Notification นั้นๆ

จริงๆแล้ว ไม่จำเป็นต้องกำหนด Content Title และ Content Text ก็ยังสามารถสร้าง Notification ได้

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

ทำไมต้องใช้คลาส NotificationCompat?

ข้อมูลของ Notification จะอยู่ในรูปของคลาส Notification ก็จริง แต่จะเห็นว่าตอนที่สร้างคลาสดังกล่าวขึ้นมา เจ้าของบล็อกสร้างจากคลาส NotificationCompat แทน

นั่นก็เพราะว่าคลาส NotificationCompat เป็นคลาสที่อยู่ใน Android Jetpack ที่จะช่วยเรื่อง Backward Compatible เพื่อลดปัญหา Fragmentation บนแอนดรอยด์ เพราะ Notification ของแอนดรอยด์ในแต่ละเวอร์ชันมีการเพิ่มความสามารถใหม่ๆเข้ามาตลอด

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

แสดง Notification ด้วย Notification Manager

เมื่อเตรียมข้อมูลสำหรับ Notification เสร็จเรียบร้อยแล้ว ก็ถึงเวลาส่งข้อมูล Notification ให้ Notification Manager เพื่อแสดงให้ผู้ใช้เห็นด้วยคำสั่งแบบนี้

val id = 0
val notification: Notification = /* ... */
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.notify(id, notification)

นอกจากข้อมูลของ Notification แล้ว ยังมีสิ่งอีกอย่างที่นักพัฒนาต้องกำหนดทุกครั้งเวลาสั่งให้ Notification Manager แสดง Notification นั่นก็คือ Notification ID

Notification ID

ID ของ Notification จะต้องเป็น Unique ID ที่ไม่ซ้ำกับ Notification ตัวอื่นๆที่อยู่ในแอปเดียวกัน กำหนดค่าเป็นตัวเลขได้สูงสุด 4 หลัก (ตั้งแต่ 0 ถึง 9999)

ถ้ามี Notification หลายตัวแต่เผลอกำหนด ID ซ้ำกัน จะทำให้ Notification ตัวล่าสุดไปแสดงทับตัวที่แสดงก่อนหน้าทันที แต่เมื่อกำหนดเป็นคนละ ID ก็จะมองว่าเป็น Notification คนละตัวกัน ทำให้ระบบแสดง Notification แยกกัน

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

เสร็จเรียบร้อยแล้วจ้า

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

โดยการสร้าง Notification แบบที่ง่ายที่สุดจะมีขั้นตอนทั้งหมดดังนี้

  • ต้องสร้าง Notification Channel และ Notification Channel Group ก่อนที่จะแสดง Notification เสมอ
  • สร้างคลาส Notification จากคลาส NotificationCompat เพื่อกำหนดข้อมูลของ Notification ที่ให้แสดง
  • ใช้ NotificationManager เพื่อแสดง Notification ตามข้อมูลที่กำหนดไว้

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

แต่จะเป็นคำสั่งอะไรบ้างนั้น… เจอกันบทความหน้าจ้าาาา