我在使用FCM推送通知消息服务时遇到问题,因为我已经重写了handleIntent()
方法,以便在应用程序位于前台时接收通知。我也在使用onMessageReceived()
方法。
但是当应用程序在后台时,我会收到2个通知,其中一个只会打开应用程序并运行MainActivity
而另一个正在打开应用程序我想要的方式。< / p>
仅供参考:我在前台时收到的通知正是我希望它打开的方式。
这是我在下面写的代码:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private final String NOTIFICATION_TYPE = "type";
private final String NOTIFICATION_ID = "id";
private final String NOTIFICATION_TYPE_PRODUCT_DETAIL = "productdetail";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String title = remoteMessage.getNotification().getTitle();R
String body = remoteMessage.getNotification().getBody();
String token = remoteMessage.getFrom();
Log.d("FireBase TAG: ", token);
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d("FireBaseMessageService","FireBase Data payload : " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
@Override
public void handleIntent(Intent intent) {
super.handleIntent(intent);
String type = intent.getExtras().getString(NOTIFICATION_TYPE, "");
int id = 0;
try {
id = Integer.valueOf(intent.getExtras().getString(NOTIFICATION_ID, ""));
} catch (NumberFormatException e) {
e.printStackTrace();
}
//Intents
Intent mainIntent = MainActivity.newIntent(this);
Intent editProfileIntent = EditProfileActivity.newIntent(this);
Intent settingsIntent = SettingsActivity.newIntent(this);
Intent productIntent = ProductActivity.newNotificationIntent(this, id, false, true);
if (UserManager.getSingleton().isUserLoggedIn(getApplicationContext())) {
PendingIntent pendingIntent;
if (type.equalsIgnoreCase(NOTIFICATION_TYPE_PRODUCT_DETAIL)) {
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(mainIntent);
stackBuilder.addNextIntent(productIntent);
editProfileIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_ONE_SHOT);
}
else {
pendingIntent = PendingIntent.getActivity(this, 0, productIntent,
PendingIntent.FLAG_ONE_SHOT);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(intent.getExtras().getString("gcm.notification.title"))
.setContentText(intent.getExtras().getString("gcm.notification.body"))
.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
}
}
我已从NotificationCompat.Builder
方法中删除了onMessageReceived()
。
但我仍然在后台收到两封通知。
App Gradle:
compile 'com.google.firebase:firebase-core:11.4.2' //Firebase
compile 'com.google.firebase:firebase-messaging:11.4.2' //Firebase Cloud Messaging
我尝试在线搜索解决方案,但不幸的是没有针对Android的解决方案。
答案 0 :(得分:1)
您正在将通知内容处理为handleIntent(Intent intent)
。您应该删除super.handleIntent(intent);
,以防止Firebase系统在应用处于后台时处理通知。
解决方案:删除super.handleIntent(intent);
答案 1 :(得分:0)
只需创建一个sendnotification()方法并设置你想传递的任何参数,如body,即sendnotification(String body)。使用待定意图启动您的活动,当您点击通知时,您的应用会将数据解析为清单中定义的启动器活动,因此,一旦您在启动器活动中有数据,您就可以使用意图将数据发送到其他活动。
我认为.setContentText(&#34;&#34;)的调用次数超过1次,你是否会收到两次相同的通知?
答案 2 :(得分:0)
是, 当您在后台应用时,您将收到系统托盘的推送,因此系统托盘将创建带有通知标题和消息的推送。 当您点击推送时,您的初始启动器活动(在清单中提到的启动器)将会打开。
您可以在启动器活动(包)中获取通知数据。
private void handlePush() {
Intent intent = null;
if (bundle.getString("push_type") != null && bundle.getString("push_type").length() > 0) {
switch (bundle.getString("push_type")) {
case PUSH_TYPE_FOLLOW_USER: {
intent = new Intent(this, ProfileExternalActivity.class);
intent.putExtra(Constants.USER_ID, Integer.parseInt(bundle.getString("id")));
intent.putExtra(Constants.FROM_PUSH_NOTIFICATION_SPLASH, true);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
break;
}
}
if (intent != null)
startActivity(intent);
finish();
}
}
并且您需要检查activty是否有数据
if (bundle != null)
handlePush();
else //your next activity
FYI:https://firebase.google.com/docs/cloud-messaging/android/receive
或< / p>
如果您的通知对象中有有效负载对象,则可以在通知中获取有效负载对象而不是数据对象所有时间都收到 onMessageReceived()。
答案 3 :(得分:0)
完美运行的通知是由您的代码生成的,但是当您的应用程序不在前台时,android系统会为您生成通知。在这种情况下,如果您没有控制权来发送您打算开启所需活动的意图中的数据。 在这种情况下,您必须对服务器有效负载进行一些修改。你必须在你的有效载荷中添加click_action,这就是android系统识别目标活动的方式。
有效负载示例:
{“notification”:{
"title":"Notification title",
"body":"Notification body",
"click_action":"<Your_destination_activity>",
}, "data":{
"param1":"value1",
"param2":"value2"
},
"priority":"high",
}
参考: https://firebase.google.com/docs/cloud-messaging/http-server-ref
答案 4 :(得分:0)
针对仍然存在此问题的人:
这里有一个黑客可以防止这种行为。我四处张望,似乎没有关于此的最少信息,但是如果您将实际发送的消息保存在共享的首选项中,然后在onRecieve中对该值进行检查,则可以轻松地避免这种情况。唯一的缺点是您的用户不能以通知的形式连续两次发送完全相同的消息(但是无论如何都会令人讨厌)。例如:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
SharedPreferences Settings = getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = Settings.edit();
message = remoteMessage.getNotification().getBody();
from = remoteMessage.getFrom(); //this comes through as the topic, oddly...
if(from.equals("/topics/"+userID+deviceID+"all")) {
if(!message.equals(Settings.getString("messageall",null))) {//this filters any dupe messages
utils.postNotification(title, message, context, extra, "messages");//create notification
editor.putString("messageall", message);//always update to the last message
editor.commit();
}
}
}