Mengirim pesan ke beberapa perangkat

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

Tutorial ini berfokus pada pengiriman pesan topik dari server aplikasi Anda menggunakan protokol HTTP atau XMPP untuk FCM, serta menerima dan menanganinya dalam aplikasi Android. Kita 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 sudah diselesaikan jika Anda telah menyiapkan aplikasi klien Android untuk FCM atau telah menyelesaikan langkah-langkah untuk Mengirim Pesan Pertama.

Sebelum memulai

  • Instal atau update Android Studio ke versi terbaru.

  • Pastikan project Anda memenuhi persyaratan berikut:

    • Menargetkan API level 16 (Jelly Bean) atau yang lebih baru
    • Menggunakan Gradle 4.1 atau yang lebih baru
    • 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.
    Emulator harus menggunakan image emulator dengan Google Play.

  • Login ke Firebase menggunakan Akun Google Anda.

Jika Anda 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 untuk terhubung ke aplikasi Android. Buka bagian Memahami Project Firebase untuk mempelajari project Firebase lebih lanjut.

Mendaftarkan aplikasi Anda dengan Firebase

Setelah memiliki project Firebase, Anda dapat menambahkan aplikasi Android ke dalamnya.

Buka Memahami Project Firebase untuk mempelajari lebih lanjut praktik terbaik dan pertimbangan dalam menambahkan aplikasi ke project Firebase, termasuk cara menangani beberapa varian build.

  1. Buka Firebase console.

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

    Jika Anda telah menambahkan aplikasi ke project Firebase, klik Tambahkan aplikasi untuk menampilkan opsi platform.

  3. Masukkan nama paket aplikasi Anda di kolom Nama paket Android.

  4. (Opsional) Masukkan informasi aplikasi lain: Nama aplikasi dan Sertifikat penandatanganan debug SHA-1.

  5. Klik Daftarkan aplikasi.

Menambahkan file konfigurasi Firebase

  1. Tambahkan file konfigurasi Firebase Android ke aplikasi Anda:

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

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

  2. Untuk mengaktifkan produk Firebase di aplikasi Anda, tambahkan plugin google-services ke file Gradle Anda.

    1. Di file Gradle (build.gradle) level root (level project), tambahkan aturan untuk menyertakan plugin Gradle Layanan Google. Pastikan Anda juga memiliki repositori Maven Google.

      buildscript {
      
        repositories {
          // Check that you have the following line (if not, add it):
          google()  // Google's Maven repository
        }
      
        dependencies {
          // ...
      
          // Add the following line:
          classpath 'com.google.gms:google-services:4.3.3'  // Google Services plugin
        }
      }
      
      allprojects {
        // ...
      
        repositories {
          // Check that you have the following line (if not, add it):
          google()  // Google's Maven repository
          // ...
        }
      }
      
    2. Di file Gradle modul (level aplikasi) Anda (biasanya app/build.gradle), terapkan plugin Gradle Layanan Google:

      apply plugin: 'com.android.application'
      // Add the following line:
      apply plugin: 'com.google.gms.google-services'  // Google Services plugin
      
      android {
        // ...
      }
      

Menambahkan Firebase SDK ke aplikasi Anda

  1. Pada file Gradle modul (level aplikasi) (biasanya app/build.gradle), tambahkan dependensi untuk produk Firebase yang ingin Anda gunakan di aplikasi Anda.

    Anda dapat menambahkan produk Firebase yang didukung ke aplikasi Android Anda.

    Untuk mendapatkan pengalaman yang optimal saat menggunakan Firebase Cloud Messaging, sebaiknya aktifkan Google Analytics di project Anda. Selain itu, sebagai bagian dari penyiapan Analytics, Anda perlu menambahkan Firebase SDK untuk Analytics ke aplikasi Anda.

    Analytics diaktifkan

    dependencies {
      // ...
    // Add the Firebase SDK for Google Analytics implementation 'com.google.firebase:firebase-analytics:17.4.4'
    // Add the SDK for Firebase Cloud Messaging implementation 'com.google.firebase:firebase-messaging:20.2.3'
    // Getting a "Could not find" error? Make sure that you've added // Google's Maven repository to your root-level build.gradle file }

    Analytics tidak diaktifkan

    dependencies {
      // ...
    // Add the SDK for Firebase Cloud Messaging implementation 'com.google.firebase:firebase-messaging:20.2.3'
    // Getting a "Could not find" error? Make sure that you've added // Google's Maven repository to your root-level build.gradle file }
  2. Sinkronkan aplikasi Anda untuk memastikan bahwa semua dependensi memiliki versi yang diperlukan.

  3. Jika Anda menambahkan Analytics, jalankan aplikasi Anda untuk mengirim verifikasi ke Firebase bahwa Anda telah berhasil mengintegrasikan Firebase. Jika tidak, Anda dapat melewati langkah verifikasi.

    Log perangkat Anda akan menampilkan verifikasi Firebase bahwa inisialisasi telah selesai. Jika menjalankan aplikasi pada emulator yang memiliki akses jaringan, Firebase console akan memberi tahu bahwa koneksi aplikasi Anda telah selesai.

Membuat aplikasi klien berlangganan topik

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

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:

Java

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

Kotlin+KTX

FirebaseMessaging.getInstance().subscribeToTopic("weather")
        .addOnCompleteListener { task ->
            var msg = getString(R.string.msg_subscribed)
            if (!task.isSuccessful) {
                msg = getString(R.string.msg_subscribe_failed)
            }
            Log.d(TAG, msg)
            Toast.makeText(baseContext, 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 memperluas FirebaseMessagingService. Layanan Anda harus mengganti callback onMessageReceived dan onDeletedMessages. Layanan Anda harus memproses pesan dalam waktu 20 detik sejak penerimaan (10 detik di Android Marshmallow). Rentang waktu mungkin lebih singkat bergantung pada penundaan OS yang terjadi sebelum panggilan onMessageReceived. Jika lebih dari rentang waktu itu, berbagai perilaku OS seperti 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. Ketukan pada notifikasi oleh pengguna akan membuka peluncur aplikasi 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 Activity peluncur.

Rangkuman:

Status Aplikasi Notifikasi Data Keduanya
Latar depan onMessageReceived onMessageReceived onMessageReceived
Latar belakang Baki sistem onMessageReceived Notifikasi: baki sistem
Data: di bagian tambahan dari intent.
Untuk 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 setara tidak ditetapkan dalam payload notifikasi.

Tambahkan baris berikut di dalam tag application untuk menetapkan ikon default kustom dan warna 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:

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

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

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

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 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 latar belakang

Ketika aplikasi Anda berada di latar belakang, Android akan mengarahkan pesan notifikasi ke baki sistem. Ketukan pada notifikasi oleh pengguna akan membuka peluncur aplikasi secara default.

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

Untuk insight tentang pengiriman pesan ke aplikasi Anda, lihat dasbor pelaporan FCM, yang mencatat jumlah pesan yang dikirim dan dibuka di perangkat iOS dan Android, beserta data untuk "tayangan" (notifikasi yang dilihat oleh pengguna) untuk aplikasi Android.

Aplikasi yang Dibatasi Latar Belakang (Android P atau yang lebih baru)

FCM mungkin tidak akan mengirim pesan ke aplikasi yang dimasukkan ke pembatasan latar belakang oleh pengguna (seperti melalui: Setelan -> Aplikasi dan Notifikasi -> [nama aplikasi] -> Baterai). Setelah aplikasi Anda dihapus dari pembatasan latar belakang, pesan baru ke aplikasi akan dikirimkan seperti sebelumnya. Untuk mencegah pesan yang hilang dan dampak pembatasan latar belakang lainnya, pastikan untuk menghindari perilaku buruk yang dicantumkan dalam Android vitals. Perilaku ini dapat menyebabkan perangkat Android merekomendasikan kepada pengguna untuk menerapkan pembatasan latar belakang pada aplikasi. Aplikasi Anda dapat memeriksa apakah ada pembatasan latar belakang atau tidak menggunakan: isBackgroundRestricted().

Mem-build permintaan kirim

Setelah membuat topik, baik dengan membuat instance aplikasi klien berlangganan ke topik di sisi klien atau melalui API server, Anda dapat mengirim pesan ke topik. 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/".
var topic = 'highScores';

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

// Send a message to devices subscribed to the provided topic.
admin.messaging().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 ke 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 tersebut dari kiri ke kanan. Pada ekspresi di atas, pengguna yang berlangganan satu topik apa pun tidak akan menerima pesan. Demikian pula, pengguna yang tidak berlangganan ke TopicA tidak akan menerima pesan. Namun, dengan kombinasi berikut, pengguna akan menerimanya:

  • TopicA dan TopicB
  • TopicA dan TopicC

Anda dapat menyertakan hingga lima topik dalam ekspresi bersyarat.

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.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
var message = {
  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.
admin.messaging().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(new Notification(
        "$GOOG up 1.43% on the day",
        "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day."))
    .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