Thông báo Firebase hoạt động khác nhau tuỳ thuộc vào nền trước/nền trước
trạng thái của ứng dụng nhận. Nếu bạn muốn các ứng dụng trên nền trước nhận
thì bạn sẽ cần viết mã để xử lý
lệnh gọi lại onMessageReceived
.
Để giải thích về sự khác biệt giữa tin nhắn thông báo và tin nhắn dữ liệu,
hãy xem Loại thông báo.
Xử lý thông báo
Để nhận tin nhắn, hãy sử dụng một dịch vụ mở rộng
FirebaseMessagingService
.
Dịch vụ của bạn phải ghi đè onMessageReceived
và onDeletedMessages
lệnh gọi lại.
Khoảng thời gian xử lý thông báo có thể ngắn hơn 20 giây tuỳ thuộc vào sự chậm trễ
phát sinh trước khi gọi onMessageReceived
, bao gồm cả độ trễ hệ điều hành, thời gian khởi động ứng dụng,
luồng chính đang bị chặn bởi các thao tác khác hoặc onMessageReceived
trước đó
cuộc gọi mất quá nhiều thời gian. Sau thời gian đó, các hành vi hệ điều hành khác nhau như
quy trình
giết người hoặc của Android O
giới hạn thực thi trong nền có thể ảnh hưởng đến khả năng hoàn thành công việc của bạn.
onMessageReceived
được cung cấp cho hầu hết các loại thông báo, với những loại sau
ngoại lệ:
-
Gửi tin nhắn thông báo khi ứng dụng của bạn chạy trong nền. Trong phần này hộp đựng, thông báo sẽ được gửi đến khay hệ thống của thiết bị. Người dùng nhấn vào một thông báo mở trình chạy ứng dụng theo mặc định.
-
Tin nhắn có cả tải trọng thông báo và tải trọng dữ liệu, khi nhận ở 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 được phân phối trong phần bổ sung của ý định của 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. |
Chỉnh sửa tệp kê khai ứng dụng
Để sử dụng FirebaseMessagingService
, bạn cần thêm đoạn mã 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>
Ngoài ra, bạn nên đặt các giá trị mặc định để tuỳ chỉnh giao diện 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 những dòng này vào bên trong
Thẻ application
để đặt biểu tượng và màu sắc tuỳ chỉnh mặc đị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ị 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.
- Mọi nội dung 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.
Android sử dụng màu 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.
- Mọi nội dung thông báo không đặt rõ màu trong thông báo tải trọng.
Nếu không có biểu tượng mặc định tuỳ chỉnh nào được đặt và không có biểu tượng nào được đặt trong tải trọng thông báo, Android hiển thị biểu tượng ứng dụng có 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 hành động dựa trên
Tin nhắn từ xa
và lấy dữ liệu tin nhắn:
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. }
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ư (>100) đang chờ xử lý trong
ứng dụng của bạn trên một thiết bị cụ thể tại thời điểm ứng dụng 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 cuộc gọi lại đến FirebaseMessagingService.onDeletedMessages()
Khi thực thể ứng dụng nhận được lệnh gọi lại này,
nó sẽ thực hiện đồng bộ hoá toàn bộ với máy chủ ứng dụng của bạn. Nếu bạn chưa gửi tin nhắn cho ứng dụng qua email đó
thiết bị trong vòng 4 tuần qua, FCM sẽ không gọi onDeletedMessages()
.
Xử lý tin nhắn thông báo trong ứng dụng chạy ở chế độ nền
Khi ứng dụng của bạn chạy trong nền, Android sẽ chuyển tin nhắn thông báo đến khay hệ thống. Khi người dùng nhấn vào thông báo, trình chạy ứng dụng sẽ mở bằng cách mặc định.
Bao gồm cả các tin nhắn chứa cả thông báo và dữ liệu tải trọng (và tất cả thông báo được gửi từ Bảng điều khiển thông báo). Trong những trường hợp này, thông báo sẽ được gửi đến khay hệ thống và tải trọng dữ liệu được phân phối trong phần bổ sung của ý định của Hoạt động của trình chạy.
Để biết thông tin chi tiết về cách gửi thư đến ứng dụng của bạn, hãy xem Trang tổng quan báo cáo FCM, nơi ghi lại các số thư được gửi và mở trên thiết bị Apple và Android, cùng với dữ liệu về "lượt hiển thị" (thông báo mà người dùng nhìn thấy) đối với ứng dụng Android.
Nhận tin nhắn FCM ở chế độ khởi động trực tiếp
Các nhà phát triển muốn gửi thông báo FCM đến các ứng dụng ngay cả trước thiết bị đã mở khoá có thể cho phép một ứng dụng Android nhận tin nhắn khi thiết bị đó đang ở chế độ khởi động trực tiếp. Ví dụ: bạn có thể muốn người dùng ứng dụng của mình nhận thông báo chuông báo ngay cả trên thiết bị đã khoá.
Khi xây dựng trường hợp sử dụng này, hãy quan sát các quy tắc chung các phương pháp hay nhất và hạn chế đối với chế độ khởi động trực tiếp. Bây giờ đặc biệt quan trọng để cân nhắc khả năng hiển thị của tính năng khởi động trực tiếp tin nhắn; bất kỳ người dùng nào có quyền truy cập vào thiết bị đều có thể xem các tin nhắn này mà không cần nhập thông tin đăng nhập của người dùng.
Điều kiện tiên quyết
- Bạn phải thiết lập thiết bị cho chế độ khởi động trực tiếp.
- Thiết bị phải cài đặt phiên bản Dịch vụ Google Play gần đây (19.0.54 trở lên).
- Ứng dụng phải sử dụng SDK FCM (
com.google.firebase:firebase-messaging
) để nhận thông báo FCM.
Bật tính năng xử lý thông báo ở chế độ khởi động trực tiếp trong ứng dụng
Trong tệp Gradle cấp ứng dụng, hãy thêm phần phụ thuộc vào thư viện hỗ trợ khởi động trực tiếp FCM:
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
Thông báo tính năng khởi động trực tiếp cho
FirebaseMessagingService
của ứng dụng bằng cách thêm thuộc tínhandroid:directBootAware="true"
vào tệp kê khai ứng dụng:<service android:name=".java.MyFirebaseMessagingService" android:exported="false" android:directBootAware="true"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
Quan trọng là bạn phải đảm bảo FirebaseMessagingService
này có thể chạy ở chế độ khởi động trực tiếp. Séc
để đáp ứng các yêu cầu sau:
- Dịch vụ không được truy cập vào bộ nhớ được bảo vệ thông tin đăng nhập khi chạy ở chế độ khởi động trực tiếp.
- Dịch vụ sẽ không tìm cách sử dụng các thành phần, chẳng hạn như
Activities
,BroadcastReceivers
, hoặcServices
khác không được đánh dấu là có khả năng nhận biết khởi động trực tiếp khi chạy ở chế độ khởi động trực tiếp. - Mọi thư viện mà dịch vụ sử dụng cũng không được truy cập vào bộ nhớ được bảo vệ thông tin đăng nhập gọi các thành phần không trực tiếpBootAware khi chạy ở chế độ khởi động trực tiếp. Tức là bất kỳ thư viện nào ứng dụng dùng được gọi từ dịch vụ cần có khả năng nhận biết khởi động trực tiếp, hoặc ứng dụng cần kiểm tra xem có đang chạy ở chế độ khởi động trực tiếp hay không và không gọi phương thức đó ở chế độ đó. Ví dụ: SDK Firebase hoạt động với tính năng khởi động trực tiếp (có thể đưa vào một ứng dụng mà không cần gặp sự cố ở chế độ khởi động trực tiếp), nhưng nhiều API Firebase không hỗ trợ gọi lệnh trực tiếp chế độ khởi động.
- Nếu ứng dụng đang dùng
Application
tuỳ chỉnh, thìApplication
cũng cần phải khởi động trực tiếp nhận biết (không có quyền truy cập vào bộ nhớ được bảo vệ thông tin đăng nhập ở chế độ khởi động trực tiếp).
Để biết hướng dẫn về cách gửi thông báo đến các thiết bị ở chế độ khởi động trực tiếp, hãy xem Gửi tin nhắn được bật tính năng khởi động trực tiếp.