ข้อความตามหัวข้อใน Android

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

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

โปรดคำนึงถึงสิ่งต่อไปนี้เกี่ยวกับหัวข้อ

  • การรับส่งข้อความตามหัวข้อเหมาะกับเนื้อหา เช่น สภาพอากาศ หรือข้อมูลอื่นๆ ที่เปิดเผยต่อสาธารณะ มากที่สุด
  • ข้อความหัวข้อได้รับการเพิ่มประสิทธิภาพเพื่ออัตราการรับส่งมากกว่าเวลาในการตอบสนอง หากต้องการส่งข้อความอย่างรวดเร็วและปลอดภัยไปยัง อุปกรณ์เครื่องเดียวหรือกลุ่มอุปกรณ์ขนาดเล็ก ให้กำหนดเป้าหมายข้อความไปยังโทเค็นการลงทะเบียน ไม่ใช่หัวข้อ
  • หากต้องการส่งข้อความไปยังอุปกรณ์หลายเครื่องต่อผู้ใช้ ให้พิจารณา การรับส่งข้อความกลุ่มอุปกรณ์ สำหรับกรณีการใช้งานเหล่านั้น
  • การรับส่งข้อความตามหัวข้อรองรับการติดตามแต่ละหัวข้อได้ไม่จำกัด อย่างไรก็ตาม FCM จะบังคับใช้ขีดจำกัดในส่วนต่อไปนี้
    • อินสแตนซ์แอป 1 รายการจะติดตามหัวข้อได้ไม่เกิน 2,000 หัวข้อ
    • หากคุณใช้ การนำเข้าแบบเป็นชุด เพื่อสมัครใช้บริการอินสแตนซ์ของแอป คำขอแต่ละรายการจะจำกัดไว้ที่อินสแตนซ์ของแอป 1, 000 รายการ
    • ระบบจะจำกัดอัตราความถี่ของการสมัครใช้บริการใหม่ต่อโปรเจ็กต์ หากคุณส่งคำขอสมัครรับข้อมูลมากเกินไปในช่วงเวลาสั้นๆ FCM เซิร์ฟเวอร์จะตอบกลับด้วยการตอบกลับ 429 RESOURCE_EXHAUSTED ("โควต้าเกิน") ลองอีกครั้งโดยใช้ Exponential Backoff

สมัครใช้บริการแอปไคลเอ็นต์ไปยังหัวข้อ

แอปไคลเอ็นต์สามารถสมัครใช้หัวข้อที่มีอยู่ หรือสร้างหัวข้อใหม่ได้ เมื่อแอปไคลเอ็นต์สมัครรับข้อมูลชื่อหัวข้อใหม่ (ชื่อที่ยังไม่มีในโปรเจ็กต์ Firebase) ระบบจะสร้างหัวข้อใหม่ที่มีชื่อนั้นใน FCM และไคลเอ็นต์ใดก็ได้จะสมัครรับข้อมูลหัวข้อนั้นได้ในภายหลัง

หากต้องการสมัครรับข้อมูลหัวข้อ แอปไคลเอ็นต์จะเรียกใช้ Firebase Cloud Messaging subscribeToTopic() โดยมีชื่อหัวข้อ FCM เมธอดนี้ จะแสดงผล Task ซึ่ง Listener การเสร็จสมบูรณ์ใช้เพื่อพิจารณาว่า การสมัครใช้บริการสำเร็จหรือไม่

Kotlin

Firebase.messaging.subscribeToTopic("weather")
    .addOnCompleteListener { task ->
        var msg = "Subscribed"
        if (!task.isSuccessful) {
            msg = "Subscribe failed"
        }
        Log.d(TAG, msg)
        Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
    }

Java

FirebaseMessaging.getInstance().subscribeToTopic("weather")
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                String msg = "Subscribed";
                if (!task.isSuccessful()) {
                    msg = "Subscribe failed";
                }
                Log.d(TAG, msg);
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });

หากต้องการยกเลิกการติดตาม แอปไคลเอ็นต์จะเรียกใช้ Firebase Cloud Messaging unsubscribeFromTopic() พร้อมชื่อหัวข้อ

จัดการการสมัครรับข้อมูลหัวข้อในเซิร์ฟเวอร์

Firebase Admin SDK ช่วยให้คุณทำงานด้านการจัดการหัวข้อขั้นพื้นฐาน จากฝั่งเซิร์ฟเวอร์ได้ เมื่อมีโทเค็นการลงทะเบียน คุณจะสมัครใช้บริการและยกเลิกการสมัครใช้บริการอินสแตนซ์แอปไคลเอ็นต์ได้ครั้งละหลายรายการโดยใช้ตรรกะของเซิร์ฟเวอร์

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

คุณส่งรายการโทเค็นการลงทะเบียนไปยังFirebase Admin SDK เมธอดการสมัครใช้บริการเพื่อสมัครใช้อุปกรณ์ที่เกี่ยวข้องกับหัวข้อได้โดยทำดังนี้

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Subscribe the devices corresponding to the registration tokens to the
// topic.
getMessaging().subscribeToTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully subscribed to topic:', response);
  })
  .catch((error) => {
    console.log('Error subscribing to topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Subscribe the devices corresponding to the registration tokens to the
// topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were subscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Subscribe the devices corresponding to the registration tokens to the
# topic.
response = messaging.subscribe_to_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were subscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Subscribe the devices corresponding to the registration tokens to the
// topic.
response, err := client.SubscribeToTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were subscribed successfully")

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Subscribe the devices corresponding to the registration tokens to the
// topic
var response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were subscribed successfully");

นอกจากนี้ Admin FCM API ยังช่วยให้คุณยกเลิกการติดตามอุปกรณ์จากหัวข้อได้ด้วย โดยส่งโทเค็นการลงทะเบียนไปยังเมธอดที่เหมาะสม

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
getMessaging().unsubscribeFromTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully unsubscribed from topic:', response);
  })
  .catch((error) => {
    console.log('Error unsubscribing from topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were unsubscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Unubscribe the devices corresponding to the registration tokens from the
# topic.
response = messaging.unsubscribe_from_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were unsubscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
response, err := client.UnsubscribeFromTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were unsubscribed successfully")

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Unsubscribe the devices corresponding to the registration tokens from the
// topic
var response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were unsubscribed successfully");

เมธอด subscribeToTopic() และ unsubscribeFromTopic() จะส่งผลให้เกิดออบเจ็กต์ที่มีการตอบกลับจาก FCM ประเภทการตอบกลับมีรูปแบบเดียวกัน ไม่ว่าจะมีโทเค็นการลงทะเบียนกี่รายการที่ระบุในคำขอ ก็ตาม

ในกรณีที่เกิดข้อผิดพลาด (การตรวจสอบสิทธิ์ล้มเหลว โทเค็นหรือหัวข้อไม่ถูกต้อง ฯลฯ) วิธีการเหล่านี้จะทำให้เกิดข้อผิดพลาด ดูรายการรหัสข้อผิดพลาดทั้งหมด รวมถึงคำอธิบาย และขั้นตอนการแก้ไขได้ที่ ข้อผิดพลาดของ Admin FCM API

รับและจัดการข้อความหัวข้อ

FCM จะส่งข้อความตามหัวข้อในลักษณะเดียวกับข้อความดาวน์สตรีมอื่นๆ

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

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

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

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

บทสรุปมีดังนี้:

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

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

หากคาดว่าแอปอาจต้องใช้เวลาเกือบ 10 วินาทีในการจัดการข้อความ คุณควร กำหนดเวลางาน WorkManager หรือทำตาม คำแนะนำเกี่ยวกับ WakeLock ด้านล่าง ในบางกรณี กรอบเวลาในการจัดการข้อความอาจสั้นกว่า 10 วินาที ทั้งนี้ขึ้นอยู่กับความล่าช้าที่เกิดขึ้นก่อนการเรียกใช้ 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

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.
}

เปิดหน้าจออุปกรณ์ค้างไว้ขณะจัดการข้อความ FCM

หากแอปต้องทำให้อุปกรณ์ตื่นอยู่ขณะประมวลผลข้อความ FCM แอปจะต้อง ถือ WakeLock ในช่วงเวลานี้ หรือจะต้องสร้างงาน WorkManager WakeLock ทำงานได้ดี สำหรับกิจกรรมการประมวลผลสั้นๆ ที่อาจเกินค่าเริ่มต้นonMessageReceived ของระยะหมดเวลา สำหรับเวิร์กโฟลว์ที่ยาวนาน เช่น การส่ง RPC แบบอนุกรมหลายรายการไปยังเซิร์ฟเวอร์ การใช้ งาน WorkManager จะเหมาะสมกว่า WakeLock ในส่วนนี้ เราจะมุ่งเน้นที่วิธีใช้ WakeLock WakeLock จะป้องกันไม่ให้อุปกรณ์เข้าสู่โหมดสลีประหว่างที่แอปทำงาน ซึ่งอาจ ส่งผลให้มีการใช้แบตเตอรี่มากขึ้น ดังนั้นจึงควรใช้ WakeLock ในกรณีที่แอป ไม่ควรหยุดชั่วคราวขณะจัดการข้อความ เช่น

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

ก่อนอื่น คุณจะต้องตรวจสอบว่าแอปขอสิทธิ์ WakeLock (FCM SDK มีสิทธิ์นี้โดยค่าเริ่มต้น ดังนั้นโดยปกติแล้วจึงไม่จำเป็นต้องเพิ่มอะไร)

<uses-permission android:name="android.permission.WAKE_LOCK" />

จากนั้นแอปจะต้องรับ WakeLock เมื่อเริ่มต้นFirebaseMessagingService.onMessageReceived()การเรียกกลับและปล่อยเมื่อสิ้นสุดการเรียกกลับ

FirebaseMessagingService ที่กำหนดเองของแอป

@Override
public void onMessageReceived(final RemoteMessage message) {
  // If this is a message that is time sensitive or shouldn't be interrupted
  WakeLock wakeLock = getSystemService(PowerManager.class).newWakeLock(PARTIAL_WAKE_LOCK, "myApp:messageReceived");
  try {
    wakeLock.acquire(TIMEOUT_MS);
    // handle message
    ...
  finally {
    wakeLock.release();
  }
}

ลบล้าง onDeletedMessages

ในบางกรณี FCM อาจไม่ส่งข้อความ ปัญหานี้เกิดขึ้นเมื่อมีข้อความที่รอดำเนินการสำหรับแอปของคุณในอุปกรณ์หนึ่งๆ มากเกินไป (>100) ในขณะที่เชื่อมต่อ หรือหากอุปกรณ์ไม่ได้เชื่อมต่อกับ FCM นานกว่า 1 เดือน ในกรณีเหล่านี้ คุณอาจได้รับการเรียกกลับไปยัง FirebaseMessagingService.onDeletedMessages() เมื่ออินสแตนซ์ของแอปได้รับการเรียกกลับนี้ อินสแตนซ์ควรทำการซิงค์แบบเต็มกับเซิร์ฟเวอร์แอป หากคุณไม่ได้ส่งข้อความไปยังแอปในอุปกรณ์ดังกล่าวภายใน 4 สัปดาห์ที่ผ่านมา FCM จะไม่โทรหา onDeletedMessages()

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

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

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

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

สร้างคำขอส่ง

หลังจากสร้างหัวข้อแล้ว ไม่ว่าจะโดยการสมัครรับข้อมูลอินสแตนซ์แอปไคลเอ็นต์ไปยังหัวข้อในฝั่งไคลเอ็นต์หรือผ่าน API ของเซิร์ฟเวอร์ คุณจะส่งข้อความไปยังหัวข้อได้ หากคุณสร้างคำขอส่งสำหรับ FCM เป็นครั้งแรก โปรดดูคำแนะนำเกี่ยวกับ สภาพแวดล้อมของเซิร์ฟเวอร์และ FCM เพื่อดูข้อมูลพื้นฐานและการตั้งค่าที่สำคัญ

ในตรรกะการส่งที่แบ็กเอนด์ ให้ระบุชื่อหัวข้อที่ต้องการ ดังที่แสดง

Node.js

// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';

const message = {
  data: {
    score: '850',
    time: '2:45'
  },
  topic: topic
};

// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

Java

// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";

// See documentation on defining a message payload.
Message message = Message.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .setTopic(topic)
    .build();

// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Python

# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'

# See documentation on defining a message payload.
message = messaging.Message(
    data={
        'score': '850',
        'time': '2:45',
    },
    topic=topic,
)

# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Go

// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Topic: topic,
}

// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

C#

// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";

// See documentation on defining a message payload.
var message = new Message()
{
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
    Topic = topic,
};

// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

REST

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
  "message":{
    "topic" : "foo-bar",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message"
      }
   }
}

คำสั่ง cURL

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "message": {
    "topic" : "foo-bar",
    "notification": {
      "body": "This is a Firebase Cloud Messaging Topic Message!",
      "title": "FCM Message"
    }
  }
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

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

"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"

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

  • TopicA และ TopicB
  • TopicA และ TopicC

คุณใส่หัวข้อในนิพจน์แบบมีเงื่อนไขได้สูงสุด 5 หัวข้อ

หากต้องการส่งไปยังเงื่อนไข ให้ทำดังนี้

Node.js

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
const condition = '\'stock-GOOG\' in topics || \'industry-tech\' in topics';

// See documentation on defining a message payload.
const message = {
  notification: {
    title: '$FooCorp up 1.43% on the day',
    body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
  },
  condition: condition
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

Java

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
Message message = Message.builder()
    .setNotification(Notification.builder()
        .setTitle("$GOOG up 1.43% on the day")
        .setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
        .build())
    .setCondition(condition)
    .build();

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Python

# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"

# See documentation on defining a message payload.
message = messaging.Message(
    notification=messaging.Notification(
        title='$GOOG up 1.43% on the day',
        body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
    ),
    condition=condition,
)

# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Go

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Condition: condition,
}

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

C#

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
var message = new Message()
{
    Notification = new Notification()
    {
        Title = "$GOOG up 1.43% on the day",
        Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
    },
    Condition = condition,
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

REST

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
   "message":{
    "condition": "'dogs' in topics || 'cats' in topics",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message",
    }
  }
}

คำสั่ง cURL

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "notification": {
    "title": "FCM Message",
    "body": "This is a Firebase Cloud Messaging Topic Message!",
  },
  "condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

ขั้นตอนถัดไป