Mengirim pesan ke beberapa perangkat

Firebase Cloud Messaging menyediakan dua cara untuk menargetkan pesan ke beberapa perangkat:

  • Pesan topik dapat digunakan untuk mengirim pesan ke beberapa perangkat yang mengikuti topik tertentu.
  • Pesan grup perangkat dapat digunakan untuk mengirim satu pesan ke beberapa perangkat yang merupakan bagian dari grup yang Anda tetapkan.

Tutorial ini berfokus pada pengiriman pesan topik dari server aplikasi Anda menggunakan Admin SDK atau REST API untuk FCM, serta penerimaan dan penanganan pesan tersebut di aplikasi Android. Kami akan membahas penanganan pesan untuk aplikasi yang dijalankan di latar belakang dan latar depan. Semua langkah untuk mencapai hal ini akan dibahas, mulai dari penyiapan sampai verifikasi.

Menyiapkan SDK

Bagian ini membahas langkah-langkah yang mungkin telah diselesaikan ketika Anda menyiapkan aplikasi klien Android untuk FCM atau ketika bersiap Mengirim Pesan Pertama.

Sebelum memulai

  • Instal atau update Android Studio ke versi terbaru.

  • Pastikan project Anda memenuhi persyaratan berikut:

    • Menarget API level 19 (KitKat) atau yang lebih tinggi
    • Menggunakan Android 4.4 atau yang lebih tinggi
    • Menggunakan Jetpack (AndroidX), termasuk memenuhi persyaratan versi berikut ini:
      • com.android.tools.build:gradle v3.2.1 atau yang lebih baru
      • compileSdkVersion 28 atau yang lebih baru
  • Siapkan perangkat fisik atau gunakan emulator untuk menjalankan aplikasi Anda.
    Perhatikan bahwa Firebase SDK yang memiliki dependensi pada layanan Google Play mengharuskan layanan Google Play diinstal di perangkat atau emulator.

  • Login ke Firebase menggunakan akun Google Anda.

Jika belum memiliki project Android dan hanya ingin mencoba produk Firebase, download salah satu contoh panduan memulai.

Membuat project Firebase

Agar dapat menambahkan Firebase ke aplikasi Android, Anda perlu membuat project Firebase yang akan dihubungkan ke aplikasi Android. Buka bagian Memahami Project Firebase untuk mempelajari project Firebase lebih lanjut.

Mendaftarkan aplikasi ke Firebase

Untuk menggunakan Firebase di aplikasi Android, Anda perlu mendaftarkan aplikasi ke project Firebase. Mendaftarkan aplikasi sering kali disebut sebagai "menambahkan" aplikasi ke project Anda.

  1. Buka Firebase console.

  2. Di bagian tengah halaman ringkasan project, klik ikon Android () atau Add app untuk meluncurkan alur kerja penyiapan.

  3. Masukkan nama paket aplikasi Anda di kolom Android package name.

  4. (Opsional) Masukkan informasi aplikasi yang lain: App nickname dan Debug signing certificate SHA-1.

  5. Klik Register app.

Menambahkan file konfigurasi Firebase

  1. Download, lalu tambahkan file konfigurasi Android Firebase (google-services.json) ke aplikasi Anda:

    1. Klik Download google-services.json untuk mendapatkan file konfigurasi Android Firebase Anda.

    2. Pindahkan file konfigurasi ke direktori root modul (level aplikasi) aplikasi Anda.

  2. Agar nilai dalam file konfigurasi google-services.json Anda dapat diakses oleh Firebase SDK, Anda memerlukan plugin Gradle layanan Google (google-services).

    1. Dalam file Gradle level root (level project), <project>/build.gradle, tambahkan plugin layanan Google sebagai dependensi buildscript:

      buildscript {
      
          repositories {
            // Make sure that you have the following two repositories
            google()  // Google's Maven repository
            mavenCentral()  // Maven Central repository
          }
      
          dependencies {
            ...
      
            // Add the dependency for the Google services Gradle plugin
            classpath 'com.google.gms:google-services:4.3.15'
          }
      }
      
      allprojects {
        ...
      
        repositories {
          // Make sure that you have the following two repositories
          google()  // Google's Maven repository
          mavenCentral()  // Maven Central repository
        }
      }
      
    2. Dalam file Gradle modul (level aplikasi), biasanya <project>/<app-module>/build.gradle, tambahkan plugin layanan Google:

      plugins {
          id 'com.android.application'
      
          // Add the Google services Gradle plugin
          id 'com.google.gms.google-services'
          ...
      }
      

Menambahkan Firebase SDK ke aplikasi

  1. Dalam file Gradle modul (level aplikasi), biasanya <project>/<app-module>/build.gradle, tambahkan dependensi untuk library Android Firebase Cloud Messaging. Sebaiknya gunakan Firebase Android BoM untuk mengontrol pembuatan versi library.

    Untuk mendapatkan pengalaman yang optimal saat menggunakan Firebase Cloud Messaging, sebaiknya aktifkan Google Analytics di project Firebase dan tambahkan Firebase SDK untuk Google Analytics ke aplikasi Anda.

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:32.1.0')
    
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging'
        implementation 'com.google.firebase:firebase-analytics'
    }
    

    Dengan menggunakan Firebase Android BoM, aplikasi Anda akan selalu menggunakan versi library Android Firebase yang kompatibel.

    (Alternatif) Tambahkan dependensi library Firebase tanpa menggunakan BoM

    Jika memilih untuk tidak menggunakan Firebase BoM, Anda harus menentukan setiap versi library Firebase di baris dependensinya.

    Perlu diperhatikan bahwa jika Anda menggunakan beberapa library Firebase di aplikasi, sebaiknya gunakan BoM untuk mengelola versi library, yang memastikan bahwa semua versi kompatibel.

    dependencies {
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging:23.1.2'
        implementation 'com.google.firebase:firebase-analytics:21.3.0'
    }
    

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:32.1.0')
    
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging-ktx'
        implementation 'com.google.firebase:firebase-analytics-ktx'
    }
    

    Dengan menggunakan Firebase Android BoM, aplikasi Anda akan selalu menggunakan versi library Android Firebase yang kompatibel.

    (Alternatif) Tambahkan dependensi library Firebase tanpa menggunakan BoM

    Jika memilih untuk tidak menggunakan Firebase BoM, Anda harus menentukan setiap versi library Firebase di baris dependensinya.

    Perlu diperhatikan bahwa jika Anda menggunakan beberapa library Firebase di aplikasi, sebaiknya gunakan BoM untuk mengelola versi library, yang memastikan bahwa semua versi kompatibel.

    dependencies {
        // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-messaging-ktx:23.1.2'
        implementation 'com.google.firebase:firebase-analytics-ktx:21.3.0'
    }
    

  2. Sinkronkan project Android Anda dengan file Gradle.

Membuat aplikasi klien berlangganan topik

Aplikasi klien dapat berlangganan topik yang ada atau membuat topik baru. Jika aplikasi klien berlangganan nama topik baru (nama yang belum ada untuk project Firebase Anda), topik baru dengan nama tersebut akan dibuat di FCM sehingga semua klien dapat berlangganan topik tersebut.

Untuk berlangganan topik, aplikasi klien memanggil subscribeToTopic() Firebase Cloud Messaging dengan nama topik FCM. Metode ini menampilkan Task, yang dapat digunakan oleh pemroses penyelesaian untuk menentukan apakah langganan berhasil atau tidak:

Kotlin+KTX

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();
            }
        });

Untuk berhenti berlangganan, aplikasi klien memanggil unsubscribeFromTopic() Firebase Cloud Messaging dengan nama topik.

Menerima dan menangani pesan topik

FCM mengirim pesan topik dengan cara yang sama seperti pesan downstream lainnya.

Untuk menerima pesan, gunakan layanan yang menyediakan FirebaseMessagingService. Layanan Anda harus mengganti callback onMessageReceived dan onDeletedMessages. Layanan Anda harus menangani pesan dalam waktu 20 detik sejak penerimaan (10 detik di Android Marshmallow). Rentang waktu tersebut bisa jadi lebih singkat, bergantung pada penundaan OS yang terjadi sebelum panggilan onMessageReceived. Jika lebih dari rentang waktu itu, berbagai perilaku OS, misalnya batas eksekusi latar belakang Android O, dapat mengganggu kemampuan Anda untuk menyelesaikan pekerjaan. Untuk mengetahui informasi lebih lanjut, lihat ringkasan kami mengenai prioritas pesan.

onMessageReceived disediakan untuk sebagian besar jenis pesan, dengan pengecualian berikut:

  • Pesan notifikasi yang dikirim saat aplikasi berada di latar belakang. Dalam hal ini, notifikasi dikirimkan ke baki sistem perangkat. Ketika pengguna mengetuk notifikasi, peluncur aplikasi akan terbuka secara default.

  • Pesan dengan notifikasi dan payload data, saat diterima di latar belakang. Dalam hal ini, notifikasi dikirimkan ke baki sistem perangkat, dan payload data dikirimkan di bagian tambahan dari intent Aktivitas peluncur.

Rangkuman:

Status aplikasi Notifikasi Data Keduanya
Latar depan onMessageReceived onMessageReceived onMessageReceived
Latar belakang Baki sistem onMessageReceived Notifikasi: baki sistem
Data: di bagian tambahan intent.
Untuk mendapatkan informasi lebih lanjut tentang jenis pesan, lihat Notifikasi dan pesan data.

Mengedit manifes aplikasi

Untuk menggunakan FirebaseMessagingService, Anda perlu menambahkan hal berikut di manifes aplikasi:

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

Anda sebaiknya juga mengatur nilai default untuk menyesuaikan tampilan notifikasi. Anda dapat menentukan ikon dan warna default kustom yang diterapkan setiap kali nilai yang setara tidak ditetapkan dalam payload notifikasi.

Tambahkan baris berikut di dalam tag application untuk menetapkan ikon default kustom dan warna default kustom:

<!-- 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 menampilkan ikon default kustom untuk

  • Semua pesan notifikasi yang dikirim dari Notifications Composer.
  • Pesan notifikasi yang tidak secara eksplisit menetapkan ikon dalam payload notifikasi.

Android menggunakan warna default kustom untuk

  • Semua pesan notifikasi yang dikirim dari Notifications Composer.
  • Pesan notifikasi yang tidak secara eksplisit menetapkan warna dalam payload notifikasi.

Jika tidak ada ikon default kustom yang ditetapkan dan tidak ada ikon yang ditetapkan dalam payload notifikasi, Android akan menampilkan ikon aplikasi dengan warna putih.

Mengganti onMessageReceived

Dengan mengganti metode FirebaseMessagingService.onMessageReceived, Anda dapat melakukan tindakan berdasarkan objek RemoteMessage yang diterima dan mendapatkan data pesan:

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

Mengganti onDeletedMessages

Dalam beberapa situasi, FCM mungkin tidak mengirimkan pesan. Hal ini terjadi jika ada terlalu banyak pesan (>100) yang tertunda untuk aplikasi Anda pada perangkat tertentu saat terhubung, atau jika perangkat belum terhubung ke FCM selama lebih dari satu bulan. Dalam hal ini, Anda mungkin akan menerima callback ke FirebaseMessagingService.onDeletedMessages(). Saat menerima callback ini, instance aplikasi harus melakukan sinkronisasi penuh dengan server aplikasi. Jika Anda belum mengirim pesan ke aplikasi pada perangkat tersebut dalam 4 minggu terakhir, FCM tidak akan memanggil onDeletedMessages().

Menangani pesan notifikasi dalam aplikasi di latar belakang

Ketika aplikasi Anda berada di latar belakang, Android akan mengarahkan pesan notifikasi ke baki sistem. Ketika pengguna mengetuk notifikasi, peluncur aplikasi akan terbuka secara default.

Ini termasuk pesan yang berisi notifikasi dan payload data (dan semua pesan yang dikirim dari konsol Notifications). Dalam hal ini, notifikasi dikirim ke baki sistem perangkat dan payload data dikirim di bagian tambahan intent Aktivitas peluncur.

Untuk melihat data terkait pengiriman pesan ke aplikasi Anda, lihat dasbor pelaporan FCM, yang mencatat jumlah pesan yang terkirim dan dibuka di perangkat Apple dan Android, beserta data untuk "tayangan" (notifikasi yang dilihat oleh pengguna) untuk aplikasi Android.

Membangun permintaan kirim

Setelah membuat topik, baik dengan membuat instance aplikasi klien berlangganan topik di sisi klien maupun melalui API server, Anda dapat mengirim pesan ke topik tersebut. Jika ini adalah pertama kalinya Anda membangun permintaan kirim untuk FCM, baca panduan lingkungan server dan FCM guna mengetahui informasi penting tentang penyiapan dan latar belakang.

Dalam logika pengiriman Anda di backend, tentukan nama topik yang diinginkan seperti yang ditunjukkan di bawah:

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

Perintah 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

Untuk mengirim pesan ke kombinasi topik, tentukan kondisi, yang merupakan ekspresi boolean yang menentukan topik target. Misalnya, kondisi berikut akan mengirim pesan ke perangkat yang berlangganan TopicA dan juga TopicB atau TopicC:

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

FCM mengevaluasi terlebih dahulu setiap kondisi di dalam tanda kurung, lalu mengevaluasi ekspresi dari kiri ke kanan. Pada ekspresi di atas, pengguna yang hanya berlangganan satu topik apa pun tidak akan menerima pesan. Demikian pula, pengguna yang tidak berlangganan TopicA tidak akan menerima pesan. Namun, pengguna dengan kombinasi berikut akan menerimanya:

  • TopicA dan TopicB
  • TopicA dan TopicC

Anda dapat menyertakan hingga lima topik dalam ekspresi kondisional.

Untuk mengirim ke sebuah kondisi:

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",
    }
  }
}

Perintah 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

Langkah berikutnya