Buka konsol

Mengirim pesan ke beberapa perangkat

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

  • Pengiriman pesan topik dapat digunakan untuk mengirim pesan ke beberapa perangkat yang mengikuti topik tertentu.
  • Dengan messaging grup perangkat, Anda dapat mengirim pesan ke beberapa perangkat yang merupakan bagian dari grup yang Anda tetapkan.

Tutorial ini berfokus pada pengiriman pesan topik dari server aplikasi Anda menggunakan protokol HTTP atau XMPP untuk FCM, serta menerima dan menanganinya dalam aplikasi web. Kita akan membahas penanganan pesan untuk aplikasi yang dijalankan di background dan foreground.

Menyiapkan SDK

Bagian ini membahas langkah-langkah yang mungkin sudah Anda selesaikan jika Anda telah menyiapkan aplikasi klien JavaScript untuk FCM atau telah menyelesaikan langkah-langkah untuk menerima pesan.

Menambahkan Firebase ke project JavaScript

Jika belum melakukannya, tambahkan Firebase ke project JavaScript Anda.

Mengambil objek messaging

// Retrieve Firebase Messaging object.
const messaging = firebase.messaging();

Meminta izin untuk menerima notification

Metode Notification.requestPermission() dari Web Notifications API menampilkan dialog persetujuan agar pengguna dapat mengizinkan aplikasi Anda untuk menerima notification di browser. Jika izin ditolak, permintaan token pendaftaran FCM akan mengalami error.

Notification.requestPermission().then((permission) => {
  if (permission === 'granted') {
    console.log('Notification permission granted.');
    // TODO(developer): Retrieve an Instance ID token for use with FCM.
    // ...
  } else {
    console.log('Unable to get permission to notify.');
  }
});

Mengakses token pendaftaran

Bagian ini menjelaskan cara pengambilan token pendaftaran untuk instance aplikasi, serta cara memantau peristiwa refresh pada token. Karena token bisa diputar setelah startup awal, Anda harus memantau peristiwa refresh pada token dan selalu mengambil token pendaftaran terbaru.

Token pendaftaran dapat berubah jika:

  • Aplikasi web menghapus token pendaftaran.
  • Pengguna membersihkan data browser. Jika ini terjadi, panggil getToken untuk mengambil token baru.

Mengambil token pendaftaran terbaru

Apabila Anda perlu mengambil token terbaru, panggil getToken. Jika izin tidak diberikan, metode ini menampilkan null. Jika izin diberikan, metode tersebut akan menampilkan token atau menolak promise karena terjadi error.

Layanan pengiriman pesan membutuhkan file firebase-messaging-sw.js. Kalau Anda belum memiliki file firebase-messaging-sw.js, buat file kosong dengan nama tersebut, lalu letakkan di root domain Anda sebelum mengambil token. Anda dapat menambahkan konten yang bermakna ke file ini nanti dalam proses penyiapan klien.

Untuk mengambil token terbaru:

// Get Instance ID token. Initially this makes a network call, once retrieved
// subsequent calls to getToken will return from cache.
messaging.getToken().then((currentToken) => {
  if (currentToken) {
    sendTokenToServer(currentToken);
    updateUIForPushEnabled(currentToken);
  } else {
    // Show permission request.
    console.log('No Instance ID token available. Request permission to generate one.');
    // Show permission UI.
    updateUIForPushPermissionRequired();
    setTokenSentToServer(false);
  }
}).catch((err) => {
  console.log('An error occurred while retrieving token. ', err);
  showToken('Error retrieving Instance ID token. ', err);
  setTokenSentToServer(false);
});

Memantau refresh pada token

Callback onTokenRefresh aktif setiap kali token baru dibuat, sehingga memanggil getToken sesuai konteksnya akan memastikan bahwa Anda mengakses token pendaftaran yang tersedia saat ini.

// Callback fired if Instance ID token is updated.
messaging.onTokenRefresh(() => {
  messaging.getToken().then((refreshedToken) => {
    console.log('Token refreshed.');
    // Indicate that the new Instance ID token has not yet been sent to the
    // app server.
    setTokenSentToServer(false);
    // Send Instance ID token to app server.
    sendTokenToServer(refreshedToken);
    // ...
  }).catch((err) => {
    console.log('Unable to retrieve refreshed token ', err);
    showToken('Unable to retrieve refreshed token ', err);
  });
});

Setelah token didapatkan, kirim token ke server aplikasi dan simpan menggunakan metode yang dipilih. Anda dapat menggunakan API server ID Instance untuk mendapatkan informasi tentang langganan

Membuat aplikasi klien berlangganan topik

Dengan token pendaftaran dan nama topik, Anda dapat menambahkan token ke topik menggunakan API server Google Instance ID. Panggil API ID Instance di endpoint ini dengan memberikan token pendaftaran dan nama topik instance aplikasi:

 https://iid.googleapis.com/iid/v1/<REGISTRATION_TOKEN>/rel/topics/<TOPIC_NAME>

Misalnya, untuk membuat instance aplikasi berlangganan ke topik berjudul "movies", kirim permintaan POST berikut dari server ke endpoint dan tambahkan kunci API server di header otorisasi seperti berikut:

https://iid.googleapis.com/iid/v1/nKctODamlM4:CKrh_PC8kIb7O...clJONHoA/rel/topics/movies
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

Jangan pernah mengirimkan permintaan jenis ini dari klien karena sensitifnya kunci server.

Permintaan yang berhasil akan menampilkan HTTP 200 OK. Untuk mengetahui informasi lebih lanjut tentang respons terhadap error dan cara mengirim permintaan batch, baca bagian Membuat peta hubungan untuk instance aplikasi

Anda dapat meneruskan daftar token pendaftaran ke metode berlangganan Firebase Admin SDK agar perangkat terkait ikut berlangganan topik:

Node.js

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

// Subscribe the devices corresponding to the registration tokens to the
// topic.
admin.messaging().subscribeToTopic(registrationTokens, topic)
  .then(function(response) {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully subscribed to topic:', response);
  })
  .catch(function(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");

Dengan Admin FCM API, Anda juga dapat menghentikan langganan perangkat dari sebuah topik dengan meneruskan token pendaftaran ke metode yang sesuai:

Node.js

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

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
admin.messaging().unsubscribeFromTopic(registrationTokens, topic)
  .then(function(response) {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully unsubscribed from topic:', response);
  })
  .catch(function(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");

Metode subscribeToTopic() dan unsubscribeFromTopic() menghasilkan objek yang berisi respons dari FCM. Jenis kembalian ini memiliki format yang sama terlepas dari jumlah token pendaftaran yang ditentukan dalam permintaan tersebut.

Jika terjadi error (kegagalan autentikasi, token atau topik tidak valid, dll.), metode ini akan mengakibatkan error. Untuk mengetahui daftar lengkap kode error, termasuk deskripsi dan langkah-langkah penyelesaiannya, baca bagian Error pada Admin FCM API.

Menerima dan menangani pesan topik

Perilaku pesan berbeda-beda, tergantung pada apakah halaman berada di foreground (mendapatkan fokus), di background, tersembunyi di balik tab lain, atau tertutup sepenuhnya. Dalam semua kasus, halaman harus menangani callback onMessage. Namun dalam kasus background, Anda mungkin juga perlu menangani setBackgroundMessageHandler atau mengonfigurasi notification tampilan agar pengguna dapat memindahkan aplikasi web Anda ke foreground.

Status Aplikasi Notification Data Keduanya
Foreground onMessage onMessage onMessage
Background (pekerja layanan) Notification yang ditampilkan oleh SDK setBackgroundMessageHandler Notification yang ditampilkan oleh SDK

Menangani pesan ketika aplikasi web berada di foreground

Untuk menerima peristiwa onMessage, aplikasi Anda harus menentukan pekerja layanan messaging Firebase dalam firebase-messaging-sw.js. Pilihan lainnya, Anda dapat menentukan pekerja layanan yang ada dengan useServiceWorker.

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': 'YOUR-SENDER-ID'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

Ketika aplikasi Anda ada di foreground (pengguna melihat halaman web Anda), Anda dapat menerima payload data dan notification secara langsung di halaman.

// Handle incoming messages. Called when:
// - a message is received while the app has focus
// - the user clicks on an app notification created by a service worker
//   `messaging.setBackgroundMessageHandler` handler.
messaging.onMessage((payload) => {
  console.log('Message received. ', payload);
  // ...
});

Menangani pesan saat aplikasi web ada di background

Semua pesan yang diterima saat aplikasi ada di background memicu notification tampilan di browser. Anda dapat menentukan pilihan untuk notification ini, seperti judul atau tindakan klik, baik dalam permintaan kirim dari server aplikasi Anda, atau menggunakan logika pekerja layanan pada klien.

Mengatur pilihan notification dalam permintaan kirim

Untuk pesan notification yang dikirim dari server aplikasi, FCM JavaScript API mendukung kunci fcm_options.link. Biasanya hal ini diatur ke halaman dalam aplikasi web Anda:

https://fcm.googleapis.com//v1/projects/<YOUR-PROJECT-ID>/messages:send
Content-Type: application/json
Authorization: bearer <YOUR-ACCESS-TOKEN>

{
  "message": {
    "topic": "matchday"
    "notification": {
      "title": "Background Message Title",
      "body": "Background message body"
    },
    "webpush": {
      "fcm_options": {
        "link": "https://dummypage.com"
      }
    }
  }
}

Jika nilai link menunjuk ke halaman yang sudah terbuka di tab browser, klik pada notification akan membawa tab tersebut ke foreground. Jika halaman belum terbuka, klik pada notification akan membuka halaman di tab baru.

Karena pesan data tidak mendukung fcm_options.link, sebaiknya Anda menambahkan payload notification ke semua pesan data. Atau Anda dapat menangani notification menggunakan pekerja layanan.

Penjelasan mengenai perbedaan antara pesan notification dan pesan data dapat dibaca di bagian Jenis pesan.

Menetapkan opsi notification dalam pekerja layanan

Untuk pesan data, Anda dapat menyetel opsi notification di pekerja layanan. Pertama, inisialisasikan aplikasi Anda dalam pekerja layanan:

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
  'messagingSenderId': 'YOUR-SENDER-ID'
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

Untuk menyetel pilihan, panggil setBackgroundMessageHandler di firebase-messaging-sw.js. Dalam contoh ini, kami membuat notification dengan kolom judul, isi, dan ikon.

messaging.setBackgroundMessageHandler(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  const notificationTitle = 'Background Message Title';
  const notificationOptions = {
    body: 'Background Message body.',
    icon: '/firebase-logo.png'
  };

  return self.registration.showNotification(notificationTitle,
    notificationOptions);
});

Membuat permintaan kirim

Dari sisi server, mengirim pesan ke topik Firebase Cloud Messaging sangat mirip dengan mengirim pesan ke setiap perangkat atau ke grup pengguna. Server aplikasi menetapkan kunci to dengan nilai seperti /topics/yourTopic. Developer bisa memilih nama topik apa pun yang cocok dengan ekspresi reguler: "/topics/[a-zA-Z0-9-_.~%]+".

Permintaan HTTP POST topik

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

Mengirim dengan 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!",
  },
  "topic" : "foo-bar"
}' "https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1"

Respons HTTP topik

{
    "name": "projects/myproject-b5ae1/messages/5735743068807585451"
}

Pesan XMPP topik

Mengirim ke sebuah topik:

<message id="">
  <gcm xmlns="google:mobile:data">
{
  "to" : /topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}
  </gcm>
</message>

Respons XMPP topik

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}