Nhận thông báo trong ứng dụng Android

Chọn nền tảng: iOS+ Android Web Flutter Unity C++


Để nhận thông báo, bạn có thể sử dụng một dịch vụ mở rộng FirebaseMessagingService. Dịch vụ của bạn phải ghi đè các lệnh gọi lại onMessageReceived và onDeletedMessages. Để xem ví dụ hoàn chỉnh, hãy xem mẫu bắt đầu nhanh về Giải pháp gửi thông báo qua đám mây của Firebase.

onMessageReceived được cung cấp cho hầu hết các loại thông báo, ngoại trừ những trường hợp sau:

  • Thông báo được gửi khi ứng dụng của bạn chạy ở chế độ nền. Trong trường hợp này, thông báo sẽ được gửi đến khay hệ thống của thiết bị. Theo mặc định, khi người dùng nhấn vào một thông báo, trình chạy ứng dụng sẽ mở ra.

  • Tin nhắn có cả tải trọng thông báo và tải trọng dữ liệu, khi nhận được ở chế độ nền. Trong trường hợp này, thông báo sẽ được gửi đến khay hệ thống của thiết bị và tải trọng dữ liệu sẽ được gửi trong phần bổ sung của ý định trong Hoạt động của trình chạy.

Tóm lại:

Trạng thái ứng dụng Thông báo Dữ liệu Cả hai
Màu nổi onMessageReceived onMessageReceived onMessageReceived
Thông tin khái quát Khay hệ thống onMessageReceived Thông báo: khay hệ thống Dữ liệu: trong phần bổ sung của ý định.

Để biết thêm thông tin về các loại thông báo, hãy xem bài viết Thông báo và thông báo dữ liệu.

Lệnh gọi lại onMessageReceived có thời gian thực thi ngắn. Nhiều yếu tố có thể ảnh hưởng đến thời lượng của khoảng thời gian này, bao gồm cả độ trễ của hệ điều hành, thời gian khởi động ứng dụng, luồng chính bị chặn bởi các thao tác khác hoặc các lệnh gọi onMessageReceived trước đó mất quá nhiều thời gian.

Vì lý do này, bạn nên tránh các tác vụ chạy trong thời gian dài (chẳng hạn như tìm nạp hình ảnh từ máy chủ để hiển thị trong thông báo) trong onMessageReceived, thay vào đó, hãy lên lịch cho một tác vụ bằng WorkManager để xử lý mọi tác vụ có thể mất hơn vài giây để hoàn tất. Để biết thêm thông tin về mức độ ưu tiên của thông báo và mức độ ảnh hưởng của mức độ ưu tiên đó đến quá trình xử lý, hãy xem phần Xử lý thông báo đối với thông báo có mức độ ưu tiên cao và bình thường.

Chỉnh sửa tệp kê khai ứng dụng

Để sử dụng FirebaseMessagingService, bạn cần thêm nội dung sau vào tệp kê khai ứng dụng:

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

Bạn nên đặt giá trị mặc định để tuỳ chỉnh giao diện của thông báo. Bạn có thể chỉ định biểu tượng mặc định tuỳ chỉnh và màu mặc định tuỳ chỉnh được áp dụng bất cứ khi nào các giá trị tương đương không được đặt trong tải trọng thông báo.

Thêm các dòng này vào bên trong thẻ application để đặt biểu tượng mặc định tuỳ chỉnh và màu sắc tuỳ chỉnh:

<!-- 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 hiển thị và sử dụng biểu tượng mặc định tuỳ chỉnh cho

  • Tất cả thông báo được gửi từ Trình soạn thông báo trong bảng điều khiển Firebase.

  • Mọi thông báo không đặt biểu tượng một cách rõ ràng trong tải trọng thông báo.

Nếu bạn không đặt biểu tượng mặc định tuỳ chỉnh và không đặt biểu tượng trong tải trọng thông báo, thì Android sẽ hiển thị biểu tượng ứng dụng được kết xuất bằng màu trắng.

Ghi đè onMessageReceived

Bằng cách ghi đè phương thức FirebaseMessagingService.onMessageReceived, bạn có thể thực hiện các hành động dựa trên đối tượng RemoteMessage nhận được và lấy dữ liệu thông báo:

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

Ghi đè onDeletedMessages

Trong một số trường hợp, FCM có thể không gửi được tin nhắn. Điều này xảy ra khi có quá nhiều thông báo (>100) đang chờ xử lý cho ứng dụng của bạn trên một thiết bị cụ thể tại thời điểm thiết bị kết nối hoặc nếu thiết bị chưa kết nối với FCM trong hơn một tháng. Trong những trường hợp này, bạn có thể nhận được lệnh gọi lại đến FirebaseMessagingService.onDeletedMessages(). Khi nhận được lệnh gọi lại này, phiên bản ứng dụng sẽ thực hiện đồng bộ hoá hoàn toàn với máy chủ ứng dụng. Nếu bạn chưa gửi tin nhắn đến ứng dụng trên thiết bị đó trong vòng 4 tuần qua, thì FCM sẽ không gọi onDeletedMessages().

Xử lý thông báo trong ứng dụng chạy ở chế độ nền

Khi ứng dụng của bạn ở chế độ nền, Android sẽ chuyển thông báo đến khay hệ thống. Theo mặc định, khi người dùng nhấn vào thông báo, trình chạy ứng dụng sẽ mở ra.

Điều này bao gồm các thông báo chứa cả thông báo và tải trọng dữ liệu (và tất cả thông báo được gửi từ Trình soạn thông báo trong bảng điều khiển Firebase). Trong những trường hợp này, thông báo sẽ được gửi đến khay hệ thống của thiết bị và tải trọng dữ liệu sẽ được gửi trong phần bổ sung của ý định trong Hoạt động của trình chạy.

Để biết thông tin chi tiết về việc gửi thông báo đến ứng dụng, hãy chuyển đến trang tổng quan DevOps & Engagement (DevOps và mức độ tương tác) > Messaging (Nhắn tin) > Reports (Báo cáo) trong bảng điều khiển Firebase. Trang tổng quan này ghi lại số lượng tin nhắn được gửi và mở trên thiết bị Apple và thiết bị Android, cùng với dữ liệu về "số lượt hiển thị" (thông báo mà người dùng nhìn thấy) cho ứng dụng Android.