Catch up on highlights from Firebase at Google I/O 2023. Learn more

รับข้อความในแอป Android

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

การจัดการข้อความ

หากต้องการรับข้อความ ให้ใช้บริการที่ขยาย FirebaseMessagingService บริการของคุณควรแทนที่การเรียกกลับ onMessageReceived และ onDeletedMessages

กรอบเวลาในการจัดการข้อความอาจสั้นกว่า 20 วินาที ขึ้นอยู่กับความล่าช้าที่เกิดขึ้นก่อนการโทร onMessageReceived รวมถึงความล่าช้าของระบบปฏิบัติการ เวลาเริ่มต้นแอป เธรดหลักถูกบล็อกโดยการดำเนินการอื่นๆ หรือการโทร onMessageReceived ก่อนหน้านี้ใช้เวลานานเกินไป หลังจากนั้น พฤติกรรมของ OS ต่างๆ เช่น การฆ่ากระบวนการ ของ Android หรือ ขีดจำกัดการดำเนินการในเบื้องหลัง ของ Android O อาจขัดขวางความสามารถของคุณในการทำงานให้เสร็จ

onMessageReceived มีให้สำหรับประเภทข้อความส่วนใหญ่ โดยมีข้อยกเว้นต่อไปนี้:

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

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

สรุป:

สถานะแอป การแจ้งเตือน ข้อมูล ทั้งคู่
เบื้องหน้า onMessageReceived onMessageReceived onMessageReceived
พื้นหลัง ถาดระบบ onMessageReceived การแจ้งเตือน: ถาดระบบ
ข้อมูล: ในส่วนเพิ่มเติมของเจตนา
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับประเภทข้อความ ดู การแจ้งเตือนและข้อความข้อมูล

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

จัดการข้อความแจ้งเตือนในแอปเบื้องหลัง

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

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

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

รับข้อความ FCM ในโหมดบูตโดยตรง

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

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

ข้อกำหนดเบื้องต้น

  • ต้องตั้งค่าอุปกรณ์สำหรับโหมดบูตโดยตรง
  • อุปกรณ์ต้องติดตั้งบริการ Google Play เวอร์ชันล่าสุด (19.0.54 หรือใหม่กว่า)
  • แอปต้องใช้ FCM SDK ( com.google.firebase:firebase-messaging ) เพื่อรับข้อความ FCM

เปิดใช้งานการจัดการข้อความในโหมดบูตโดยตรงในแอปของคุณ

  1. ในไฟล์ Gradle ระดับแอป ให้เพิ่มการอ้างอิงในไลบรารีสนับสนุนการบูตโดยตรงของ FCM:

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. ทำให้ทราบการบูตโดยตรงของ FirebaseMessagingService ของแอปโดยเพิ่มแอตทริบิวต์ android:directBootAware="true" ในรายการแอป:

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

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