不会相应地调用FirebaseMessagingService的onMessageSent [英] onMessageSent of FirebaseMessagingService is not called accordingly
问题描述
我正尝试使用FCM
发送UpStream Message
,所以我按照google上的教程进行了操作.
如下面MainActivity
中的代码所示,当单击按钮时,我发送Upstream message
,然后在MyAndroidFirebaseMsgService
中,我应该看到一条Log
消息,如下所示
在MyAndroidFirebaseMsgService
下.
但是发生的是,即使我多次按下按钮,也不会显示onMessageSent
中MyAndroidFirebaseMsgService
中的Log
消息.
仅当从FCM
向应用程序发送downstream message
时,才能显示onMessageSent
中MyAndroidFirebaseMsgService
中Log
中的Log
消息,在这种情况下,
将显示MyAndroidFirebaseMsgService
中的内容.
请让我知道为什么发送UpStream message
后为什么onMessageSent
中的Log消息没有显示?以及如何解决.
主要活动:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnSendUpstreamMsg = (Button) findViewById(R.id.btn_send_upstream_message);
mBtnSendUpstreamMsg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FirebaseMessaging fm = FirebaseMessaging.getInstance();
fm.send(new RemoteMessage.Builder("673xxxxx" + "@gcm.googleapis.com")
.setMessageId("2")
.addData("my_message", "Hello World")
.addData("my_action","SAY_HELLO")
.build());
}
});
}
MyAndroidFirebaseMsgService :
public class MyAndroidFirebaseMsgService extends FirebaseMessagingService {
private final static String TAG = MyAndroidFirebaseMsgService.class.getSimpleName();
@Override
public void onMessageSent(String s) {
super.onMessageSent(s);
Log.d(TAG, "onMessageSent: upstream message");
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "onMessageReceived: downstream message");
//Log data to Log Cat
Log.d(TAG, "onMessageReceived->From: " + remoteMessage.getFrom());
Log.d(TAG, "onMessageReceived->Notification Message Body: " + remoteMessage.getNotification().getBody());
//create notification
createNotification(remoteMessage.getNotification().getBody());
}
private void createNotification( String messageBody) {
Intent intent = new Intent( this , ResultActivity.class );
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent resultIntent = PendingIntent.getActivity( this , 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder( this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Android Tutorial Point FCM Tutorial")
.setContentText(messageBody)
.setAutoCancel( true )
.setSound(notificationSoundURI)
.setContentIntent(resultIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, mNotificationBuilder.build());
}
}
是的,可以发送Firebase消息推送通知并使用onMessageReceived
在所有应用程序生命周期中接收它. >
但是有必要更改默认的Firebase行为,先拦截意图请求.
** 重要提示 **
这是Firebase的愚蠢想法,方法是:当FCM消息以notification message
格式出现时,取消开发人员的处理能力,但对于data message
则不行.
这创建了一堆"解决方法";在许多解决方案中,使得分析学和其他所有东西都弄糟了.
如果我已经设计了此解决方案,那么我总是会用completion handle
调用onMessageReceived
方法.让开发人员决定该怎么做(免费的技巧,Firebase).
使用onMessageReceived
是正确的方法.此方法是唯一带来RemoteMessage
对象的方法,该对象具有您需要的所有信息.它是专为此设计的.您在正确的路径上.
** 如何做 **
在扩展了FirebaseMessagingService
的Firebase类MyAndroidFirebaseMsgService
中,重写公共方法handleIntent
以在Firebase捕获意图请求之前对其进行拦截.
@Override
public void handleIntent(Intent intent){
if(intent.hasExtra("google.message_id")){
intent = handleFirebaseIntent(intent);
}
super.handleIntent(intent);
}
之后,将notification message
程序包转换为data message
,从意图中删除所有"gcm.notification.%"
和"gcm.n.%"
附加功能,然后将"gcm.notification.title"
,"gcm.notification.body"
和"gcm.notification.image"
元素转换为所需的内容:
// Thank you Google, for that brilliant idea to treat notification message and notification data
// differently on Android, depending of what app life cycle is. Because of that, all the developers
// are doing "workarounds", using data to send push notifications, and that's not what you planned for.
// Let the developers decide what to do on their apps and ALWAYS deliver the notification
// to "onMessageReceived" method. Its simple, is freedom and its what the creative ones need.
private Intent handleFirebaseIntent(Intent intent){
//printIntentExtras(intent);
String FCM_TITLE_KEY = "gcm.notification.title";
String FCM_BODY_KEY = "gcm.notification.body";
String FCM_IMAGE_KEY = "gcm.notification.image";
String title = intent.getStringExtra(FCM_TITLE_KEY);
String body = intent.getStringExtra(FCM_BODY_KEY);
String image = intent.getStringExtra(FCM_IMAGE_KEY);
// Remove the key extras that identifies an Notification type message
Bundle bundle = intent.getExtras();
if (bundle != null) {
for (String key : bundle.keySet()) {
if (key.startsWith("gcm.notification.") || key.startsWith("gcm.n."))
{
intent.removeExtra(key);
}
}
}
Boolean isTitleEmpty = StringUtils.isNullOrEmpty(title);
Boolean isBodyEmpty = StringUtils.isNullOrEmpty(body);
Boolean isImageEmpty = StringUtils.isNullOrEmpty(image);
// Notification title and body has prevalence over Data title and body
if(
!isTitleEmpty || !isBodyEmpty || !isImageEmpty
){
// This is my personalized translation method, designed for my solution.
// Probably you gonna need to do it by your own
String contentData = intent.getStringExtra(Definitions.PUSH_NOTIFICATION_CONTENT);
Map<String, Object> content;
if(StringUtils.isNullOrEmpty(contentData)){
content = new HashMap<String, Object>();
content.put(Definitions.NOTIFICATION_ID, new Random().nextInt(65536) - 32768);
content.put(Definitions.NOTIFICATION_CHANNEL_KEY, "basic_channel" );
} else {
content = JsonUtils.fromJson(new TypeToken<Map<String, Object>>(){}.getType(),contentData);
}
if(!isTitleEmpty) content.put(Definitions.NOTIFICATION_TITLE, title);
if(!isBodyEmpty) content.put(Definitions.NOTIFICATION_BODY, body);
if(!isImageEmpty){
content.put(Definitions.NOTIFICATION_BIG_PICTURE, image);
content.put(Definitions.NOTIFICATION_LAYOUT, NotificationLayout.BigPicture.toString());
}
contentData = JsonUtils.toJson(content);
intent.putExtra(Definitions.PUSH_NOTIFICATION_CONTENT, contentData);
}
//printIntentExtras(intent);
return intent;
}
private void printIntentExtras(Intent intent){
Bundle bundle;
if ((bundle = intent.getExtras()) != null) {
for (String key : bundle.keySet()) {
System.out.println(key + " : " + (bundle.get(key) != null ? bundle.get(key) : "NULL"));
}
}
}
您可以在此处查看我的整个解决方案.
I am trying to use FCM
to send UpStream Message
, so I followed the tutorial on google and it works.
As shown in the code below in MainActivity
, I send Upstream message
when the button is clicked, then in MyAndroidFirebaseMsgService
I should see a Log
message as shown
below in MyAndroidFirebaseMsgService
.
But what happen is, the Log
messages in MyAndroidFirebaseMsgService
in onMessageSent
in do not get displayed even I kept pressing the button several times.
the Log
message in MyAndroidFirebaseMsgService
in onMessageSent
can be displayed only if sent a downstream message
from FCM
to the App, in this case, both the Logs
in
in MyAndroidFirebaseMsgService
will be displayed.
Please let me know why the Log message in onMessageSent
is not getting displayed once there is an UpStream message
sent?and how to fix it.
Mainactivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnSendUpstreamMsg = (Button) findViewById(R.id.btn_send_upstream_message);
mBtnSendUpstreamMsg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FirebaseMessaging fm = FirebaseMessaging.getInstance();
fm.send(new RemoteMessage.Builder("673xxxxx" + "@gcm.googleapis.com")
.setMessageId("2")
.addData("my_message", "Hello World")
.addData("my_action","SAY_HELLO")
.build());
}
});
}
MyAndroidFirebaseMsgService:
public class MyAndroidFirebaseMsgService extends FirebaseMessagingService {
private final static String TAG = MyAndroidFirebaseMsgService.class.getSimpleName();
@Override
public void onMessageSent(String s) {
super.onMessageSent(s);
Log.d(TAG, "onMessageSent: upstream message");
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "onMessageReceived: downstream message");
//Log data to Log Cat
Log.d(TAG, "onMessageReceived->From: " + remoteMessage.getFrom());
Log.d(TAG, "onMessageReceived->Notification Message Body: " + remoteMessage.getNotification().getBody());
//create notification
createNotification(remoteMessage.getNotification().getBody());
}
private void createNotification( String messageBody) {
Intent intent = new Intent( this , ResultActivity.class );
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent resultIntent = PendingIntent.getActivity( this , 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder( this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Android Tutorial Point FCM Tutorial")
.setContentText(messageBody)
.setAutoCancel( true )
.setSound(notificationSoundURI)
.setContentIntent(resultIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, mNotificationBuilder.build());
}
}
Yes, is possible to send a Firebase messaging push notification and receive it in all app life cycles using onMessageReceived
.
But is necessary to change the default Firebase behaviour, intercepting the intent request before everything else.
** IMPORTANT NOTE **
This was a pretty stupid idea from Firebase by remove the developers processment capability when the FCM message arives with the notification message
format, but not for data message
.
This created a bunch of "workarounds" in many solutions, which made the analythics and everything else being messed up.
If I had designed this solution, I would always call the onMessageReceived
method with a completion handle
. Let the developer decide what to do (free tip for you, Firebase).
Use onMessageReceived
is the correct way to do. This method is the only one who brings RemoteMessage
object, that have every information what you need. It was designed for it. You are on correct path.
** HOW TO DO **
In your Firebase Class MyAndroidFirebaseMsgService
, which extends FirebaseMessagingService
, override the public method handleIntent
to intercep the intent request before Firebase catch it.
@Override
public void handleIntent(Intent intent){
if(intent.hasExtra("google.message_id")){
intent = handleFirebaseIntent(intent);
}
super.handleIntent(intent);
}
After, transform the notification message
package into an data message
, removing all "gcm.notification.%"
and "gcm.n.%"
extras from intent, and translating "gcm.notification.title"
, "gcm.notification.body"
and "gcm.notification.image"
elements into what you need:
// Thank you Google, for that brilliant idea to treat notification message and notification data
// differently on Android, depending of what app life cycle is. Because of that, all the developers
// are doing "workarounds", using data to send push notifications, and that's not what you planned for.
// Let the developers decide what to do on their apps and ALWAYS deliver the notification
// to "onMessageReceived" method. Its simple, is freedom and its what the creative ones need.
private Intent handleFirebaseIntent(Intent intent){
//printIntentExtras(intent);
String FCM_TITLE_KEY = "gcm.notification.title";
String FCM_BODY_KEY = "gcm.notification.body";
String FCM_IMAGE_KEY = "gcm.notification.image";
String title = intent.getStringExtra(FCM_TITLE_KEY);
String body = intent.getStringExtra(FCM_BODY_KEY);
String image = intent.getStringExtra(FCM_IMAGE_KEY);
// Remove the key extras that identifies an Notification type message
Bundle bundle = intent.getExtras();
if (bundle != null) {
for (String key : bundle.keySet()) {
if (key.startsWith("gcm.notification.") || key.startsWith("gcm.n."))
{
intent.removeExtra(key);
}
}
}
Boolean isTitleEmpty = StringUtils.isNullOrEmpty(title);
Boolean isBodyEmpty = StringUtils.isNullOrEmpty(body);
Boolean isImageEmpty = StringUtils.isNullOrEmpty(image);
// Notification title and body has prevalence over Data title and body
if(
!isTitleEmpty || !isBodyEmpty || !isImageEmpty
){
// This is my personalized translation method, designed for my solution.
// Probably you gonna need to do it by your own
String contentData = intent.getStringExtra(Definitions.PUSH_NOTIFICATION_CONTENT);
Map<String, Object> content;
if(StringUtils.isNullOrEmpty(contentData)){
content = new HashMap<String, Object>();
content.put(Definitions.NOTIFICATION_ID, new Random().nextInt(65536) - 32768);
content.put(Definitions.NOTIFICATION_CHANNEL_KEY, "basic_channel" );
} else {
content = JsonUtils.fromJson(new TypeToken<Map<String, Object>>(){}.getType(),contentData);
}
if(!isTitleEmpty) content.put(Definitions.NOTIFICATION_TITLE, title);
if(!isBodyEmpty) content.put(Definitions.NOTIFICATION_BODY, body);
if(!isImageEmpty){
content.put(Definitions.NOTIFICATION_BIG_PICTURE, image);
content.put(Definitions.NOTIFICATION_LAYOUT, NotificationLayout.BigPicture.toString());
}
contentData = JsonUtils.toJson(content);
intent.putExtra(Definitions.PUSH_NOTIFICATION_CONTENT, contentData);
}
//printIntentExtras(intent);
return intent;
}
private void printIntentExtras(Intent intent){
Bundle bundle;
if ((bundle = intent.getExtras()) != null) {
for (String key : bundle.keySet()) {
System.out.println(key + " : " + (bundle.get(key) != null ? bundle.get(key) : "NULL"));
}
}
}
You can check my entire solution here.
这篇关于不会相应地调用FirebaseMessagingService的onMessageSent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!