Mengirim pesan ke beberapa perangkat

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

  • Messaging 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 messaging 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 latar belakang dan latar depan.

Menyiapkan SDK

Bagian ini membahas langkah-langkah yang 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 notifikasi

Metode Notification.requestPermission() dari Web Notifications API menampilkan dialog izin agar pengguna dapat mengizinkan aplikasi Anda untuk menerima notifikasi 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

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

Layanan messaging memerlukan file firebase-messaging-sw.js. Kalau Anda belum memiliki file firebase-messaging-sw.js, buat file kosong dengan nama itu, 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 dengan konteksnya memastikan bahwa Anda mengakses token pendaftaran terbaru yang tersedia.

// 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 memperoleh token, kirim token ke server aplikasi dan simpan menggunakan metode yang Anda pilih. 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 Instance ID API 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 informasi lebih lanjut tentang respons terhadap error dan cara mengirim sekumpulan permintaan, lihat 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 yang ditampilkan ini memiliki format yang sama terlepas dari jumlah token pendaftaran yang ditentukan dalam permintaan tersebut.

Jika terjadi error (kegagalan autentikasi, token tidak valid, atau topik, dll.) metode ini 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 latar depan (difokus), di latar belakang, tersembunyi di balik tab lain, atau tertutup sepenuhnya. Dalam semua kasus, halaman harus menangani callback onMessage. Namun dalam kasus latar belakang, Anda juga harus menangani setBackgroundMessageHandler atau mengonfigurasi notifikasi tampilan untuk memungkinkan pengguna memindahkan aplikasi web Anda ke latar depan.

Status Aplikasi Notifikasi Data Keduanya
Latar depan onMessage onMessage onMessage
Latar belakang (pekerja layanan) Notifikasi yang ditampilkan oleh SDK setBackgroundMessageHandler Notifikasi yang ditampilkan oleh SDK

Menangani pesan saat aplikasi web ada di latar depan

Untuk menerima peristiwa onMessage, aplikasi Anda harus menentukan pekerja layanan messaging Firebase dalam firebase-messaging-sw.js. Atau, 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 latar depan (pengguna melihat halaman web Anda), Anda dapat menerima payload data dan notifikasi 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 latar belakang

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

Mengatur pilihan notifikasi dalam permintaan kirim

Untuk pesan notifikasi 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 notifikasi akan membawa tab tersebut ke latar depan. Jika halaman belum terbuka, klik pada notifikasi akan membuka halaman di tab baru.

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

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

Menetapkan opsi notifikasi dalam pekerja layanan

Untuk pesan data, Anda dapat menyetel opsi notifikasi 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 notifikasi 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 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"
}