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

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

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

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

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

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

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

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

จัดการข้อความการแจ้งเตือนในแอปที่ทำงานอยู่เบื้องหลัง

เมื่อแอปอยู่ในเบื้องหลัง Android จะส่งข้อความการแจ้งเตือนไปยัง ถาดระบบ เมื่อผู้ใช้แตะการแจ้งเตือน ระบบจะเปิดตัวเปิดแอปโดยค่าเริ่มต้น

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

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

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

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

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

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

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

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

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

    implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
    
  2. ทำให้การเปิดเครื่อง 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 จะต้องรองรับการบูตโดยตรงด้วย (ไม่มีสิทธิ์เข้าถึงพื้นที่เก็บข้อมูลที่ปกป้องด้วยข้อมูลเข้าสู่ระบบในโหมดการบูตโดยตรง)

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