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

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

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

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

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

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

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

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

สรุป:

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

แก้ไขรายการแอป

หากต้องการใช้ FirebaseMessagingService คุณต้องเพิ่มสิ่งต่อไปนี้ในรายการแอปของคุณ:

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

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