สำหรับการพัฒนาแอปในยุคนี้เป็นเรื่องปกติที่จะต้องมีฟีเจอร์เกี่ยวกับ Push Notification ที่จะทำให้ฝั่ง Web Service สามารถส่งข้อมูล ๆ ใดให้ Client ได้ โดยที่ไม่ต้องรอให้ Client ส่ง Request เพื่อขอข้อมูลนั้น ๆ เช่น แสดงข้อความเพื่อแจ้งเตือนเพื่อบอกให้ผู้ใช้รู้ว่ามีส่วนลดภายในแอป เป็นต้น ซึ่งข้อดีของการใช้ Push Notification ก็คือผู้ใช้ไม่จำเป็นต้องเปิดแอปก็รับข้อมูลได้ (ตราบใดที่เชื่อมต่อกับอินเตอร์เน็ตอยู่)
ซึ่งการทำ Push Notification บนแอนดรอยด์ก็จะต้องพึ่งพาบริการของ Firebase Cloud Messaging อย่างเลี่ยงไม่ได้ (สำหรับอุปกรณ์แอนดรอยด์ที่ติดตั้ง Google Apps หรือ Google Play Services) และถึงแม้จะใช้บริการอย่าง OneSignal, CleverTap หรือ Blaze สุดท้ายแล้วเบื้องหลังการทำงานของบริการเหล่านี้ก็ใช้ Firebase Cloud Messaging อยู่ดี
โดยหนึ่งในขั้นตอนสำคัญของการทำ Push Notification ก็คือนักพัฒนาจะต้องรับ Token ที่ได้จาก Google Play Services ที่ติดตั้งอยู่ภายในเครื่อง แล้วส่งให้ Web Service เก็บไว้ เพื่อใช้ตอนที่ต้องการส่งข้อมูลผ่าน Push Notification ด้วย Firebase Cloud Messaging นั่นเอง
![](https://akexorcist.dev/content/images/2023/11/firebase_crashlyics_messaging_token-001.webp)
ถ้าลองอ่าน Documentation ของ Firebase Cloud Messaging ก็จะไม่ได้อธิบายขั้นตอนนี้ไปมากกว่าการบอกว่าส่ง Token ใหม่ให้ Web Service
![](https://akexorcist.dev/content/images/2023/10/firebase_crashlyics_messaging_token-002.webp)
นักพัฒนาสามารถอ่าน Documentation สำหรับการจัดการกับ Token ของ Firebase Cloud Messaging ได้ที่ Best practices for FCM registration token management [Firebase]
โดย Token จะถูกสร้างขึ้นใหม่ได้ในหลาย ๆ เงื่อนไข เช่น Clear App Data, หรือลบแอปแล้วติดตั้งใหม่ เป็นต้น นั่นหมายความว่าแต่ละเครื่องมีโอกาสที่ Token จะเปลี่ยนแปลงได้เสมอ และสิ่งที่นักพัฒนาต้องทำก็คือส่ง Token ใหม่ให้ Web Service ในขณะที่ Web Service ก็ควรจะลบ Token เก่าทิ้งด้วยเช่นกัน
ควรเก็บ Timestamp คู่กับ Token เสมอ เพราะถ้า Token มีอายุนานเกิน 2 เดือนจะมีโอกาสสูงมากที่ Token นั้นจะใช้งานไม่ได้แล้ว
และนี่ก็คือเรื่องราวของบทความนี้ ที่จะแนะนำวิธีส่ง Token ขึ้น Web Service อย่างไรให้เหมาะสมนั่นเอง
เพราะว่าเราเขียนโค้ดสำหรับการทำงานในส่วนนี้ได้หลายแบบ
ถึงแม้ว่าการจัดการกับ Token ของ Firebase Cloud Messaging จะฟังดูเป็นเรื่องง่าย ก็แค่ส่งขึ้นไปเก็บไว้บน Web Service ก็จบแล้ว แต่ถ้าเราเขียนโค้ดในส่วนนี้ไม่ดีพอ ก็อาจจะทำให้ผู้ใช้บางคนไม่ได้รับข้อมูลผ่าน Push Notification ก็เป็นได้
ถ้าผู้ที่หลงเข้ามาอ่านไม่อยากเสียเวลาทำความเข้าใจเกี่ยวกับโค้ดในแต่ละวิธี แนะนำให้ข้ามไปดูวิธีที่ 2 หรือ 3 แล้วเลือกใช้งานได้ตามสะดวก
วิธีที่ 1 – ได้เมื่อไร ก็ส่งไปทันที (ไม่แนะนำ)
วิธีนี้จะทำการส่งข้อมูลให้ Web Service ให้ทันทีที่ได้ Token ใหม่ในขณะนั้น
// Firebase Messaging Service
override fun onNewToken(token: String) {
sendNewTokenToWebService(token)
}
วิธีนี้เป็นวิธีที่ไม่แนะนำซักเท่าไรเนื่องจากมีโอกาสที่จะเกิดปัญหาตอนส่งข้อมูลให้ Web Service ในขณะนั้นพอดี เช่น อุปกรณ์แอนดรอยด์เชื่อมต่ออินเตอร์เน็ตไม่ได้ชั่วขณะ เป็นต้น ซึ่งจะทำให้ Web Service ไม่ได้รับ Token ตัวใหม่และส่ง Push Notification ให้เครื่องนั้นไม่ได้ไปโดยปริยาย
![](https://akexorcist.dev/content/images/2023/11/firebase_crashlyics_messaging_token-003-2.webp)
วิธีที่ 2 – ลองส่งดูก่อน ถ้าไม่ได้ก็เก็บไว้ในเครื่องเพื่อส่งใหม่ตอนเปิดแอป (แนะนำ)
เพื่อรับมือกับปัญหาอุปกรณ์แอนดรอยด์ส่ง Token ให้กับ Web Service ไม่ได้ด้วยเหตุผลใด ๆ ก็ตาม จึงนำ Token ที่ได้มาเก็บไว้ใน Persistent Storage อย่าง SharedPreferences ก่อน แล้วทำการส่งให้กับ Web Service
// Firebase Messaging Service
override fun onNewToken(token: String) {
saveNewTokenToLocalStorage(token)
val result = sendNewTokenToWebService(token)
if (result.succeed) {
deleteTokenInLocalStorage()
}
}
// Application or Main Activity
if (isTokenInLocalStorageAvailable()) {
val result = sendNewTokenToWebService(token)
if (result.isSuccess) {
deleteTokenInLocalStorage()
}
}
ถ้าส่ง Token ให้กับ Web Service สำเร็จก็ให้ลบ Token ใน Persistent Storage ทิ้งไป แต่ถ้ามีปัญหาบางอย่างเกิดขึ้น ก็จะยังคงเก็บ Token นั้นไว้อยู่ และจะส่งใหม่อีกครั้งเมื่อเปิดแอปในครั้งถัดไป
![](https://akexorcist.dev/content/images/2023/12/firebase_crashlyics_messaging_token-004.webp)
วิธีนี้จะช่วยลดปัญหาการส่ง Token ไปไม่ถึง Web Service ได้ และเป็นวิธีที่นักพัฒนาส่วนใหญ่นิยมใช้กัน เพราะเป็นวิธีที่เข้าใจได้ง่าย
แต่วิธีนี้ก็จะยังมีปัญหาว่าในระหว่างที่รอส่ง Token ครั้งถัดไป จะต้องรอจนกว่าแอปจะถูกเปิดขึ้นมาใหม่อีกครั้ง นั่นหมายความว่าในระหว่างนั้น Web Service จะส่ง Push Notification มาที่เครื่องดังกล่าวไม่ได้เช่นกัน ถึงแม้จะเป็นช่วงระยะไม่นานก็ตาม
วิธีที่ 3 – เหมือนกับวิธีที่ 2 แต่ใช้ Work Manager เข้ามาช่วย (แนะนำ)
เพื่อลดช่องว่างที่อาจจะเกิดขึ้นในวิธีที่ 2 จึงใช้ประโยชน์จาก Work Manager เพื่อคอยจัดการเรื่อง Retry ให้โดยอัตโนมัติ
class UploadTokenWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
override fun doWork(): Result {
val result = sendNewTokenToWebService(token)
return if (result.succeed) {
deleteTokenInLocalStorage()
Result.success()
} else {
Result.retry()
}
}
}
อีกทั้งยังสามารถกำหนด Constraint เพื่อให้ทำงานในจังหวะที่เหมาะสมได้อีกด้วย
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val workRequest = OneTimeWorkRequestBuilder<UploadTokenWorker>()
.setConstraints(constraints)
.build()
แล้วสั่งให้ Worker ทำงานในตอนที่ได้ Token ใหม่หรือตอนที่เปิดแอปและมี Token อยู่ใน Persistent Storage นั่นเอง
// Firebase Messaging Service
override fun onNewToken(token: String) {
saveNewTokenToLocalStorage(token)
val workRequest = /* ... */
WorkManager
.getInstance(/* ... */)
.enqueue(workRequest)
}
// Application
if (isTokenInLocalStorageAvailable()) {
val workRequest = /* ... */
WorkManager
.getInstance(/* ... */)
.enqueue(workRequest)
}
ด้วยการทำงานของ Work Manager จะทำให้การส่ง Token ให้กับ Web Service ยังคงสามารถทำต่อไปได้เรื่อย ๆ เมื่อเกิดปัญหาโดยไม่จำเป็นต้องรอให้เปิดแอปขึ้นมาก่อน ช่วยลด Gap ที่ทำให้ Web Service ส่ง Push Notification ไม่ได้ให้น้อยลงนั่นเอง
![](https://akexorcist.dev/content/images/2023/12/firebase_crashlyics_messaging_token-005.png)
และสำหรับ Worst-case Scenario อย่างกรณีที่ Work Manager หยุดทำงานกระทันหัน (เช่น ปิดและเปิดเครื่องใหม่) ก็จะกลับมาทำงานใหม่อีกครั้งตอนที่แอปเริ่มทำงานจนกว่าจะส่ง Token ได้
ใช้วิธีไหนดีที่สุด?
เมื่อพิจารณาจากทั้ง 3 วิธีที่เจ้าของบล็อกหยิบมาเล่าในบทความนี้ก็จะเห็นว่าวิธีที่ 3 นั้นดูเหมือนจะมีประสิทธิภาพมากที่สุด เพราะใช้ประโยชน์จาก Work Manager เพื่อลด Gap ที่รอส่ง Token ให้ Web Service
แต่ทว่าวิธีที่ 2 ก็ไม่ได้แย่แต่อย่างใด และเป็นวิธีที่สามารถใช้งานได้จริง เพราะทำความเข้าใจได้ง่ายกว่าวิธีที่ 3 อีกทั้งโอกาสที่ Token จะส่งหา Web Service ไม่สำเร็จนั้นมีโอกาสเกิดขึ้นได้น้อยมาก และต่อให้เกิดปัญหาดังกล่าวก็อาจจะไม่ได้ร้ายแรงอะไรมากนักถ้าแอปไม่ได้ส่ง Push Notification ที่สำคัญมากในขณะนั้น
ดังนั้นจะใช้วิธีที่ 2 หรือวิธีที่ 3 ก็เลือกได้ตามใจชอบเลย แค่อย่าทำแบบวิธีที่ 1 ก็พอ