การแจ้งเตือน Firebase จะทำงานแตกต่างกันไปตามสถานะเบื้องหน้า/เบื้องหลังของแอปที่ได้รับ หากต้องการให้แอปที่ทำงานอยู่เบื้องหน้าได้รับข้อความการแจ้งเตือนหรือข้อความข้อมูล คุณจะต้องเขียนโค้ดเพื่อจัดการกับ Callback ของ onMessageReceived
โปรดดูคำอธิบายความแตกต่างระหว่างข้อความการแจ้งเตือนและข้อความข้อมูลได้ที่ประเภทข้อความ
การจัดการข้อความ
หากต้องการรับข้อความ ให้ใช้บริการที่ขยายขนาด
FirebaseMessagingService
บริการของคุณควรลบล้างการติดต่อกลับ onMessageReceived
และ onDeletedMessages
กรอบเวลาในการจัดการข้อความอาจสั้นกว่า 20 วินาทีโดยขึ้นอยู่กับความล่าช้าที่เกิดขึ้นก่อนการเรียก onMessageReceived
รวมถึงความล่าช้าของระบบปฏิบัติการ เวลาเริ่มต้นแอป เทรดหลักที่ถูกบล็อกโดยการดำเนินการอื่น หรือการเรียก onMessageReceived
ก่อนหน้าใช้เวลานานเกินไป หลังผ่านช่วงเวลาดังกล่าว ลักษณะการทำงานต่างๆ ของระบบปฏิบัติการ เช่น การหยุดทำงานของกระบวนการของ Android หรือ
ขีดจำกัดการดำเนินการในเบื้องหลังของ Android O อาจรบกวนความสามารถในการทำงานของคุณ
onMessageReceived
มีให้สำหรับข้อความส่วนใหญ่ โดยมีข้อยกเว้นต่อไปนี้
-
ข้อความแจ้งเตือนที่ส่งเมื่อแอปของคุณทำงานอยู่เบื้องหลัง ในกรณีนี้ ระบบจะส่งการแจ้งเตือนไปยังถาดระบบของอุปกรณ์ ผู้ใช้แตะการแจ้งเตือนจะเปิดเครื่องเรียกใช้งานแอปโดยค่าเริ่มต้น
-
ข้อความที่มีทั้งข้อมูลการแจ้งเตือนและเพย์โหลดข้อมูล เมื่อได้รับในเบื้องหลัง ในกรณีนี้ ระบบจะส่งการแจ้งเตือนไปยังถาดระบบของอุปกรณ์ และเพย์โหลดข้อมูลจะส่งไปในส่วนที่เกินมาจากจุดประสงค์ของกิจกรรมของ Launcher
บทสรุปมีดังนี้:
สถานะของแอป | การแจ้งเตือน | ข้อมูล | ทั้งสอง |
---|---|---|---|
พื้นหน้า | onMessageReceived |
onMessageReceived |
onMessageReceived |
ความเป็นมา | ถาดระบบ | onMessageReceived |
การแจ้งเตือน: ถาดระบบ ข้อมูล: ความสามารถเพิ่มเติมของ Intent |
แก้ไขไฟล์ Manifest ของแอป
หากต้องการใช้ FirebaseMessagingService
คุณต้องเพิ่มรายการต่อไปนี้ในไฟล์ Manifest ของแอป
<service android:name=".java.MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
นอกจากนี้ เราขอแนะนำให้กำหนดค่าเริ่มต้นเพื่อปรับแต่งรูปลักษณ์ของการแจ้งเตือนด้วย คุณระบุไอคอนเริ่มต้นที่กำหนดเองและสีเริ่มต้นที่กำหนดเองซึ่งจะใช้เมื่อไม่ได้ตั้งค่าที่เทียบเท่าในเพย์โหลดการแจ้งเตือนได้
เพิ่มบรรทัดต่อไปนี้ในแท็ก application
เพื่อตั้งค่าไอคอนเริ่มต้นที่กําหนดเองและสีที่กําหนดเอง
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages. See README(https://goo.gl/l4GJaQ) for more. --> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_stat_ic_notification" /> <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming notification message. See README(https://goo.gl/6BKBk7) for more. --> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" />
Android แสดงไอคอนเริ่มต้นที่กำหนดเองสำหรับ
- ข้อความแจ้งเตือนทั้งหมดที่ส่งจาก ตัวเขียนการแจ้งเตือน
- ข้อความแจ้งเตือนที่ไม่ได้ตั้งค่าไอคอนในเพย์โหลดการแจ้งเตือนอย่างชัดเจน
Android ใช้สีเริ่มต้นที่กำหนดเองสำหรับ
- ข้อความแจ้งเตือนทั้งหมดที่ส่งจาก ตัวเขียนการแจ้งเตือน
- ข้อความแจ้งเตือนที่ไม่ได้ตั้งค่าสีในเพย์โหลดการแจ้งเตือนอย่างชัดเจน
หากไม่ได้กำหนดไอคอนเริ่มต้นที่กำหนดเองไว้และไม่มีการตั้งค่าไอคอนในเพย์โหลดการแจ้งเตือน Android จะแสดงไอคอนแอปพลิเคชันในรูปแบบสีขาว
ลบล้าง onMessageReceived
เมื่อลบล้างเมธอด FirebaseMessagingService.onMessageReceived
คุณจะดำเนินการต่างๆ ตามออบเจ็กต์ RemoteMessage ที่ได้รับและรับข้อมูลข้อความได้ ดังนี้
Kotlin+KTX
override fun onMessageReceived(remoteMessage: RemoteMessage) { // TODO(developer): Handle FCM messages here. // Not getting messages here? See why this may be: https://goo.gl/39bRNJ Log.d(TAG, "From: ${remoteMessage.from}") // Check if message contains a data payload. if (remoteMessage.data.isNotEmpty()) { Log.d(TAG, "Message data payload: ${remoteMessage.data}") // Check if data needs to be processed by long running job if (needsToBeScheduled()) { // For long-running tasks (10 seconds or more) use WorkManager. scheduleJob() } else { // Handle message within 10 seconds handleNow() } } // Check if message contains a notification payload. remoteMessage.notification?.let { Log.d(TAG, "Message Notification Body: ${it.body}") } // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. }
Java
@Override public void onMessageReceived(RemoteMessage remoteMessage) { // TODO(developer): Handle FCM messages here. // Not getting messages here? See why this may be: https://goo.gl/39bRNJ Log.d(TAG, "From: " + remoteMessage.getFrom()); // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.getData()); if (/* Check if data needs to be processed by long running job */ true) { // For long-running tasks (10 seconds or more) use WorkManager. scheduleJob(); } else { // Handle message within 10 seconds handleNow(); } } // Check if message contains a notification payload. if (remoteMessage.getNotification() != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); } // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. }
ลบล้าง onDeletedMessages
ในบางกรณี FCM อาจไม่ส่งข้อความ กรณีนี้จะเกิดขึ้นเมื่อมีข้อความที่รอดำเนินการสำหรับแอปของคุณบนอุปกรณ์หนึ่งๆ มากเกินไป (มากกว่า 100 รายการ) ในขณะที่เชื่อมต่อ หรือหากอุปกรณ์ไม่ได้เชื่อมต่อกับ FCM นานกว่า 1 เดือน ในกรณีเหล่านี้ คุณอาจได้รับ Callback ไปยัง FirebaseMessagingService.onDeletedMessages()
เมื่ออินสแตนซ์ของแอปได้รับ Callback นี้ อินสแตนซ์ควรจะซิงค์กับเซิร์ฟเวอร์แอปของคุณอย่างเต็มรูปแบบ หากคุณไม่ได้ส่งข้อความไปยังแอปในอุปกรณ์นั้นภายใน 4 สัปดาห์ที่ผ่านมา FCM จะไม่โทรติดต่อ onDeletedMessages()
จัดการข้อความแจ้งเตือนในแอปที่ทำงานอยู่เบื้องหลัง
เมื่อแอปอยู่ในเบื้องหลัง Android จะส่งข้อความการแจ้งเตือนไปยังถาดระบบ ผู้ใช้แตะที่การแจ้งเตือนจะเปิดเครื่องเรียกใช้งานแอปโดยค่าเริ่มต้น
ซึ่งรวมถึงข้อความที่มีทั้งการแจ้งเตือนและเพย์โหลดข้อมูล (และข้อความทั้งหมดที่ส่งจากคอนโซลการแจ้งเตือน) ในกรณีเหล่านี้ ระบบจะส่งการแจ้งเตือนไปยังถาดระบบของอุปกรณ์ และเพย์โหลดข้อมูลจะส่งไปในส่วนที่เพิ่มเติมมาจากความตั้งใจของกิจกรรม Launcher
ดูข้อมูลเชิงลึกเกี่ยวกับการส่งข้อความไปยังแอปของคุณได้ที่ แดชบอร์ดการรายงาน FCM ซึ่งจะบันทึกจำนวนข้อความที่ส่งและเปิดในอุปกรณ์ Apple และ Android พร้อมทั้งข้อมูลของ "การแสดงผล" (การแจ้งเตือนที่ผู้ใช้เห็น) สำหรับแอป Android
รับข้อความ FCM ในโหมดการเปิดเครื่องโดยตรง
นักพัฒนาซอฟต์แวร์ที่ต้องการส่งข้อความ FCM ไปยังแอปก่อนที่จะปลดล็อกอุปกรณ์สามารถอนุญาตให้แอป Android รับข้อความได้เมื่ออุปกรณ์อยู่ในโหมดการเปิดเครื่องโดยตรง เช่น คุณอาจต้องการให้ผู้ใช้แอปได้รับการแจ้งเตือนการปลุกแม้ในอุปกรณ์ที่ล็อกอยู่
เมื่อสร้าง Use Case นี้ ให้สังเกตแนวทางปฏิบัติแนะนำและข้อจํากัดทั่วไปสําหรับโหมดการเปิดเครื่องโดยตรง สิ่งสำคัญคือต้องพิจารณาระดับการเข้าถึงของข้อความที่เปิดใช้การเปิดเครื่องโดยตรง ผู้ใช้ที่มีสิทธิ์เข้าถึงอุปกรณ์จะดูข้อความเหล่านี้ได้โดยไม่ต้องป้อนข้อมูลเข้าสู่ระบบของผู้ใช้
สิ่งที่ต้องดำเนินการก่อน
- ต้องตั้งค่าอุปกรณ์สำหรับโหมดเปิดเครื่องโดยตรง
- อุปกรณ์ต้องติดตั้งบริการ Google Play เวอร์ชันล่าสุด (19.0.54 ขึ้นไป)
- แอปต้องใช้ FCM SDK (
com.google.firebase:firebase-messaging
) เพื่อรับข้อความ FCM
เปิดใช้การจัดการข้อความในโหมดเปิดเครื่องโดยตรงในแอป
ในไฟล์ Gradle ระดับแอป ให้เพิ่มทรัพยากร Dependency ในไลบรารีการสนับสนุนการเปิดเครื่องโดยตรงของ FCM ดังนี้
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
ทำให้การเปิดเครื่อง
FirebaseMessagingService
โดยตรงของแอปรับรู้โดยเพิ่มแอตทริบิวต์android:directBootAware="true"
ในไฟล์ Manifest ของแอป<service android:name=".java.MyFirebaseMessagingService" android:exported="false" android:directBootAware="true"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
คุณควรตรวจสอบว่า FirebaseMessagingService
นี้ทำงานในโหมดการเปิดเครื่องโดยตรงได้ โปรดตรวจสอบข้อกำหนดต่อไปนี้
- บริการไม่ควรเข้าถึงพื้นที่เก็บข้อมูลที่ป้องกันด้วยข้อมูลเข้าสู่ระบบขณะทำงานในโหมดการเปิดเครื่องโดยตรง
- บริการไม่ควรพยายามใช้คอมโพเนนต์ เช่น
Activities
,BroadcastReceivers
หรือServices
อื่นๆ ที่ไม่ได้ทำเครื่องหมายว่าเป็นการรับรู้การเปิดเครื่องโดยตรงขณะทำงานในโหมดการเปิดเครื่องโดยตรง - ไลบรารีที่บริการใช้ต้องไม่เข้าถึงพื้นที่เก็บข้อมูลเข้าสู่ระบบหรือเรียกใช้คอมโพเนนต์ที่ไม่ใช่directBootAware ขณะทำงานในโหมดเปิดเครื่องโดยตรง ซึ่งหมายความว่าไลบรารีที่แอปใช้ซึ่งเรียกใช้จากบริการจะต้องรับรู้การเปิดเครื่องโดยตรง หรือแอปจะต้องตรวจสอบว่าแอปกำลังทำงานในโหมดการเปิดเครื่องโดยตรงหรือไม่ และไม่ได้เรียกใช้ในโหมดดังกล่าว ตัวอย่างเช่น Firebase SDK ทำงานกับการเปิดเครื่องโดยตรง (รวมอยู่ในแอปได้โดยไม่ต้องทำให้แอปขัดข้องในโหมดเปิดเครื่องโดยตรง) แต่ Firebase API จำนวนมากไม่รองรับการเรียกใช้ในโหมดเปิดเครื่องโดยตรง
- หากแอปใช้
Application
ที่กำหนดเองApplication
จะต้องรับรู้การเปิดเครื่องโดยตรงด้วย (ไม่มีสิทธิ์เข้าถึงพื้นที่เก็บข้อมูลเข้าสู่ระบบที่ได้รับการปกป้องในโหมดการเปิดเครื่องโดยตรง)
ดูคำแนะนำเกี่ยวกับการส่งข้อความไปยังอุปกรณ์ในโหมดเปิดเครื่องโดยตรงที่หัวข้อส่งข้อความที่เปิดใช้การเปิดเครื่องโดยตรง