I am struggling to find the cause for the duplicate notification message on android using Firebase, Unity and sending from nodejs with the help of node-gcm.
Here is all relative code:
Unity3d client side I got:
public class PushServiceManager : MonoBehaviour
{
public string Identifier;
public string SkuId;
public SQSParameters sqsOptions;
private SQSManager sqs;
// Use this for initialization
void Start()
{
sqs = new SQSManager(this.sqsOptions);
sqs.Initialize(this.gameObject);
Firebase.Messaging.FirebaseMessaging.TokenReceived += OnTokenReceived;
Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
}
public void OnTokenReceived(object sender, Firebase.Messaging.TokenReceivedEventArgs token)
{
Debug.Log("Received Registration Token: " + token.Token);
RegistrationToken t = new RegistrationToken();
t.id_token = token.Token;
// sends token to node server
sqs.SendRegistrationToken(t);
}
public void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e)
{
Debug.Log(e.Message.Data.ToString());
}
}
Nodejs server side:
pushNotification(pushRequest, tokens, callback) {
// This is an array of firebase tokens
let registrationTokens = tokens.map(function (token) {
return token.token;
});
let message = new gcm.Message({
timeToLive: pushRequest.ttl
});
let note = {
title: 'Message title',
icon: 'none',
sound: 'none',
body: 'message text'
};
message.addNotification(note);
let payload = {
data: {foo: "foo"}
}
message.addData(payload);
this.sender.send(message, {registrationTokens}, callback);
}
Result on device is:
Question:
Why do I get the second empty push notification?
Tapping first one opens up a unity game as expected but tapping that empty one does not.
Where am I going wrong with this?
Thank you!
01.31.17 UPDATE:
Shutout to firebase support team for looking into this issue...
I have the same duplicate notifications issue in my project and below is the solution.
Check your generated AndroidManifest.xml by unity build in [Your unity project folder]\Temp\StagingArea
Look for all receivers that have below line:
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
In my case, I have below that added by the Amazon AWS unity plugin
<receiver android:name="com.amazonaws.unity.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.amazonaws.unity" />
</intent-filter>
</receiver>
and below from Firebase plugin
<receiver android:exported="true" android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.bbbbbttttttgggg.sssssstttt" />
</intent-filter>
</receiver>
The duplicated notification is caused by amazon AWS GCMBroadcastReceiver.
There are two options to fix this.
Remove the receiver if you do not need it.
Add android:exported="false" to the receiver.
Example:
<receiver android:exported="false" android:name="com.amazonaws.unity.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.amazonaws.unity" />
</intent-filter>
</receiver>
Remember to make the change in the original AndroidManifest.xml that contains the receiver. Not the one in Temp\StagingArea. It should be one of the AndroidManifest.xml file inside [Your unity project folder]\Assets\Plugins\Android or it sub folder.
I am facing the same problem with firebase. I am using Firebase together with Microsoft Azure Notification Hub. If I send a test message via Microsoft Notification Hub I only get one message and that message is handled by my Push Handler. Otherwise if I send push notifications through firebase console I am getting two message like you(also one is empty). One message is handled by my push service and the second one is somehow handled by "no code"! I cannot find in my code where the push notification send by firebase is handled? There must be a OnReceiveMessage method in the background which handles the notification. For me I come with following solution: I just uncommented my push handler and now I am only getting one notification, but this without sound...somehow I have to override that function and implement sound behaviour. Have you found a solution for that? The empty message is caused by your push handler the second full message is handled in the background by firebase.
I also getting two different types of message in my onReceive() method:
Microsoft: Bundle[{google.sent_time=1484748187461, from=230XXXXXXXXXX, google.message_id=0:1484748187469719%8a1048bff9fd7ecd, message=Test through Microsoft, collapse_key=do_not_collapse}]
Firebase: Bundle[{google.c.a.udt=0, google.sent_time=1484748603664, gcm.notification.e=1, google.c.a.c_id=3001008833206773803, google.c.a.ts=1484748604, gcm.n.e=1, from=230XXXXXXXXXXX, google.message_id=0:1484748603943016%8a1048bf8a1048bf, gcm.notification.body=Test through firebase, google.c.a.e=1, collapse_key=com.sub_zero.ipostcard}]
So the message received through firebase is handled one time in the background somewhere maybe in through the firebase lib and the second time I suppose by your handler. That why you getting two of them...Just uncomment your push handler and test it again.
I found what was cause this issue...
I had AWS module included into the project which had it's own manifest file. In it there was a receiver declaration for "GCMBroadcastReceiver" in combination with service declaration for "GCMIntentService".
Removing those solved the issue
Related
In normal case app is alive i received the notification and i display it.
{
"to" : "xxxx",
"notification": {
"body": "Hello",
"title" : "Hello world notification"
},
"data" : {
"data1" : "dddddd",
"data2" : "mmm"
}
}
<service
android:name=".notifications.MyFirebaseMessagingService"
android:directBootAware="true"
android:exported="false"
android:enabled="true"
android:stopWithTask="false"
>
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
Since severals days i search a solution to receive notification FCM when my app is not alive.
I try to
FirebaseMessagingService / stopWithTask
Create other service to manage FirebaseMessagingService
etc.
But i don't found a good way and good practice and technical solution.
Finally it not possible to receive notification when app if not alive?
what is the good way to keep app in background and not really killed app when the user swipe?
(i use API 29)
add this code in your Manifest file OnMessageRecive not call if App is background
refer this document
https://firebase.google.com/docs/cloud-messaging/android/topic-messaging
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_ic_notification" />
Well FYI, this method doesn't gets called when the app is in background or killed because The notifications are handled by Device OS when the app is in background or killed.
So if you do not want the notifications to be handled by Device OS and wants this method to be executed even in background and killed state then follow this:
First of all, make FCM service like this by removing all unwanted codes
<service android:name=".push.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Importantly, Make changes in your fcm json payload like this by removing notification object to make OnReceivedMethod work.
{
"to" : "xxxx",
"data" : {
"bodyText": "Hello",
"titleText" : "Hello world notification",
"data1" : "dddddd",
"data2" : "mmm",
}
}
Goodmorning everyone,
I haven't been able to find a solution for several hours now.
I use the "PushNotifications" Capacitor plugin (https://capacitor.ionicframework.com/docs/apis/push-notifications/) to listen to push notifications that come to me from firebase (both notification and data type), the listening of notifications happens very well and everything behaves as expected even in cases of app killed or in the background.
The problem is the following:
I want to open the app when I receive a notification, if it is in the background or if it has been killed.
In the case of notification received when the app is in the foreground, I can run custom code using
addListener(eventName: "pushNotificationReceived", callback)
and in any case I have no problems because the app is open.
In case of notification received when the app is in the background, I can force the app to keep the backgroundMode active (https://ionicframework.com/docs/native/background-mode)
and bring the app to the foreground upon receiving a notification. (although I don't really like it because it's battery consuming)
In case of app killed, I have not found solutions to the problem.
It seems that there is no way to hook custom code to be able to run when a push notification arrives when it is received in the background or with the app killed, have you ever had this problem?
Thank you!
My solution was to add: FCM_PLUGIN_ACTIVITY action to AndroidManifest.xml
<activity
...
android:name="com.appname.MainActivity"
...>
...
...
...
<intent-filter>
<action android:name="FCM_PLUGIN_ACTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
In addition on the server you should include the action in your push notification object:
const pushNotification = {
data: {
...
},
notification: {
body: body,
title: title,
click_action: 'FCM_PLUGIN_ACTIVITY',
},
};
And inside you ionic project you handle pushNotificationActionPerformed like below and navigate to the desired route:
PushNotifications.addListener('pushNotificationActionPerformed',
(notification: PushNotificationActionPerformed) => {
console.log('Push action performed: ' + JSON.stringify(notification));
}
);
To handle receiving push notifications in when the app is open you should handle pushNotificationReceived and show a toast yourself if needed.
// the app is open, show your own notification if needed
PushNotifications.addListener('pushNotificationReceived',
(notification: PushNotification) => {
console.log('push notification received: ' + JSON.stringify(notification));
}
);
I had the same issue and fixed it with the following lines in AndroidManifest.xml
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="#string/default_notification_channel_id" />
<service android:name="com.getcapacitor.CapacitorFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
For us background-notifications (even after App was killed) also worked if we additionally installed the FCM Plugin (https://github.com/capacitor-community/fcm), which we need for iOS.
I have following manifest -
<service
android:name=".RegistrationIntentService"
android:exported="false" />
<service
android:name=".TestGcmListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.test" />
</intent-filter>
</service>
<service
android:name=".RegistrationIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.test" />
</intent-filter>
</receiver>
And following onMessageReceived method -
#Override
public void onMessageReceived(String from, Bundle data) {
ObjectMapper objectMapper = new ObjectMapper();
Message message;
try {
message = objectMapper.readValue(String.valueOf(data.get("message")), Message.class);
MessageNotification.notify(this, message, 1);
} catch (IOException e) {
e.printStackTrace();
}
}
What happens is, onMessageReceived gets called only when app is in foreground. Otherwise it doesn't get called and notification is not shown. When I open the app all notifications are shown at once.
Doesn't GcmListenereService wake up device if locked and do the work ? How to solve this ?
Googled around and managed to find this thread on github which is pretty much the same as your concern, where onMessageReceived() is only called when app is on foreground. The reason was because only Notification Messages are sent. As per the description included in the thread:
Notification Messages - these are intended to generate a notification with no intermediate processing by the application. They only hit onMessageReceived if the app is running.
Data Messages - these are intended to silently pass data to the app's messaging service. They hit onMessageReceived even if the app is in the background. The service may then choose to generate a notification using the normal system notification APIs, or it may choose to handle the message silently.
I think you are sending Notification Messages while expecting the behavior for Data Messages to kick in.
Here's also the SO post of Shiprack mentioned in the github thread. Hope this helps. Good luck.
migrating from Parse I got stuck by not being able to override PushBots notification creation code like I used to do with getNotification function in ParsePushBroadcastReceiver. My project needs multiline and separate push notifications, but PushBots default behavior is to show single line and group notifications by application.
I tried canceling notification in the onReceive function of BroadcastReceiver (PBConstants.EVENT_MSG_RECEIVE event), so I could create & display my own push, but I don't know notification ID and CancelAll() didn't work (also would be a bad idea).
Pushbots.sharedInstance() does have a setNotificationBuilder function, which accepts PBGenerate object, but I have no idea how to construct it properly and if this actually would help my case.
Couldn't find any documentation & get a response from support yet, so asking here if maybe someone knows a solution or a way to workaround this issue.
Here's how receivers are defined in AndroidManifest.xml
<receiver
android:name="com.pushbots.google.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.my.app" />
</intent-filter>
</receiver>
<receiver android:name="com.my.app.MyPushReceiver" />
<service android:name="com.pushbots.push.GCMIntentService" />
Thank you in advance!
I'm developing an Android app and I wish to use Push notifications to perform a custom task without displaying a notification to the user.
Specifically, the app is in alpha stage and I wish to be able to send a remote command to a specific device to restart a background service running in the background.
I know that you can do that with GCM. How can this be done using Parse?
You need to subclass ParsePushBroadcastReceiver and override onPushReceive() method in it. Add these lines to your manifest
<receiver android:name=".yourPushReceiverSubclass" android:exported=false>
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.OPEN" />
<action android:name="com.parse.push.intent.DELETE" />
</intent-filter>
</receiver>
Just remove call to super in the onPushReceive method and do whatever you want. If you going to send push from pars.com in JSON format, you can obtain this message using just like that:
JSONObject data = new JSONObject(intent.getExtras().getString("com.parse.Data"));