FCM showing duplicate notification when app is in background - android

I implemented FCM in my project. Push notification is working as expected, onMessageReceived is called when a notification is received. This is true when app is in the foreground.
However, when the app is in the background, the system tray always display a duplicate notification when one arrives (e.g. when Notification A is received, system tray display 2 Notification A)
How to fix this?
EDIT: added code
I extended FirebaseMessagingService class and have this in the onMessageReceived method
This is the only part in the project where I used NotificationManager.
Also, I tried to add a log on this method. onMessageReceived is called when app is in foreground. It doesn't get called when app is in background
#Override
public void onMessageReceived(RemoteMessage remoteMessage)
{
RemoteMessage.Notification notification = remoteMessage.getNotification();
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String title = notification.getTitle();
String message = notification.getBody();
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}

Same problem. I modified AndroidManifest.xml because i was requesting permissions to old GCM like this...
<uses-permission android:name="mypackage.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="mypackage.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
So, removing it from manifest and uninstalling and reinstalling the app my problem was solved.

To handle push notifications manually use handleIntent(intent) of FirebaseMessagingService.
This method gets called when application is in foreground, background and killed state. To avoid the duplication, do not call super.handleIntent(intent). This will prevent the automatic push notification when app in BG or killed state.
This worked for me.

I was having the exact same 'duplicate' problem. This may be just a workaround because I couldn't get notifications behaving when app was in foreground without the 'duplicate' problem happening. Instead I implemented a WakefulBroadcastReceiver, when toggling the android:exported to "false" it started behaving.
AndroidManifest.xml
<receiver
android:name="PACKAGE.MyWakefulBroadcastReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
MyWakefulListenerService.java
public class MyWakefulBroadcastReceiver extends WakefulBroadcastReceiver {
private final String TAG = "MyWakefulListener";
public void onReceive(Context context, Intent intent) {
sendNotification(context);
}
}

Related

startForegroundService - unable to use setContentIntent + addAction?

Unfortunately another question about my startForegroundService notification... I searched, really, I did:
I have a foreground service that is running perfectly. I would like to add a couple of actions to this notification. For one, make it so when the user clicks the notification they are sent to MainActivity as well as adding a "Quit" addAction.
Here is the snippet I am using to create the notification:
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String channelId = getNotificationChannel(notificationManager);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId);
Notification notification = notificationBuilder.setOngoing(true)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setSmallIcon(R.drawable.ic_notif_icon)
.setContentTitle("My app")
.setContentText("Background service is running...")
.setContentIntent(pendingIntent)
.build();
startForeground(13365, notification);
Using the above a notification shows up just fine, but click on it results in nothing. I also tried using addAction, also nothing. I am aware the syntax is a little bit different (....Action.Builder) when adding an addAction.
I am creating my notification in the onCreate handler of the foreground service. Running on SDK 26.
Can startForeground notifications have setContentIntent / addAction attached to them?
Thanks!
Solved : I had the notification replaced elsewhere in my application and was not adding the intents there.
Doh!

How to handle the case when click_action was sent to the previous version of the app where intent-filter was not added yet?

Could you help me to solve the problem?
The task is develop push notification that will open particular Activity by users tap.
I've added intent-filter and tried to send the push message with the click_action field, and everything works like a charm.
The problem is with the previous version of the application where Intent-filter was not added yet. If user tap on the push message (in the case of previous app version), nothing happens.
What is better to do in this case? How to handle such situations?
Edit:
So the question is, how can we have default behavior (opening the app on the last screen) in the case of specific screen mentioned in click_action field and lacking of necessary intent-filter? This relevant for situation when the user has previous version of the app without necessary intent-filter in the manifest file.
To perform some action on push-notification click we need to write code for that to perform such action. In your case you want to perform some action on your old live application, In this can you can't do anything.
To perform some action you can call this method on push notification received
private void sendNotification(String title, String messageBody) {
Intent intent = new Intent(this, YourActivityName.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle(title)
.setContentText(messageBody)
.setVibrate(new long[]{01})
.setAutoCancel(true)
.setContentIntent(pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
notificationBuilder.setSmallIcon(R.mipmap.notification);
else
notificationBuilder.setSmallIcon(R.mipmap.notification);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notificationBuilder.build());
}

Listen for downloads from other apps

My app should listen for downloads (from any app, for example Browser) and then, depending on some file attributes, offer some actions through Notifications. This should also work when the app is currently not running in the foreground, therefore I am doing it using a statically defined receiver (in AndroidManifest.xml).
However, the app never receives the "download finished" intent. This is my code:
DownloadReceiver:
public class DownloadReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// This notification is just for testing purposes
// to see if the DownloadReceiver works
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_check)
.setContentTitle("Your download has finished.")
.setContentText("Download finished");
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
}
AndroidManifest.xml:
<receiver
android:name=".DownloadReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
According to some solutions on the internet, I added android:exported=true and also android:enabled=true but neither helped. I also tried to use the constant name DownloadManager.DOWNLOAD_COMPLETE in the intent filter, but this has not helped me too. Any other solutions?
After thorough research, I found that this is not possible for privacy reasons. There is one possibility, although it's not quite easy to implement (it involves using File Observer).

Change android status bar notification every day

I want to create a constant notification on status bar (like current battery percents - it's always there), but the icon will be changed every day on 00:00.
In addition, I want this notification will alert automatically after rebooting the device and not only after the user opens the application.
I created the notification in MainActivity, but I don't know how to make it alert after rebooting and also I don't know how to change it every day at mid-night.
I tried to create AlarmService and broadcast reciever but it run every 5 seconds and it's far too much so I deleted it.
My current code is:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.notificationTitle))
.setContentText(....)
.setLargeIcon(largeIconBitmap)
.setSmallIcon(getResources().getIdentifier("icon_status_" + myHelper.getCurrentImageNumber(),"drawable", getPackageName())); // change the icon at mid-night. 'getCurrentImageNumber' should get me the right icon number
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this,0,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(mylHelper.myRequestCode, notification);
Right now I see a notification, but the icon doesn't change and it does not alarm after reboot. I saw some answers in stackoverflow but nothing helped me.
I wont give you all the code, you will need to learn by doing.
Here is what you should do:
1 Use a Service to launch your notification and maintain the logic to updating it. If the notification already exists you can update the existing one or programmatically dismiss it and replace with a new one.
2 Register a broadcast receiver in AndroidManifest.xml with multiple intent filters to launch your service.
<receiver android:name=".myReceiver">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3 Create class which extends the broadcast receiver class and use and launch the above service.

android how to create a service that make a notification in real time (like facebook or whatapps)

I'm trying to create a background service that every "X" minutes consult a webservice and if response "ok" generate a Notification on the notification Bar
I'm not sure if is a android service o Broadcast receiver the thing that I need
Thank anyways
Please, don't pull a page from web-service every X minutes -- this drains battery a lot, use Google Cloud Messaging (former C2DM -- Cloud To Device Messaging) instead to get your information updates -- it's very lightweight and very efficient and shares one existing data connection for all applications.
NotificationManager seems to be what you are looking for.
First of all you need a broadcast receiver (inside its own class, plus a bit of code in the manifest) that reacts to the USER_PRESENT action (when user unlocks screen) or the BOOT_COMPLETED (when cellphone finishes loading the OS and all other stuff). Boot activates the Broadcast, the broadcast starts the service. Inside the onStartCommand() method of your service, you run your connection to the webservice every X minutes. Your service should Implement AsyncTask to connect to the Web service. In the onCompleted() method of that task, you call the notifications.
MANIFEST:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name="classes.myReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name="classes.myService">
</service>
CLASS:
public class myReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
Intent service = new Intent(ctx, myService.class);
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)||intent.getAction().equals(Intent.ACTION_USER_PRESENT)||intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
ctx.startService(service);
}
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
ctx.stopService(service);
}
}
}
SAMPLE NOTIFICATION
private void showNotification() {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setContent(getNotificationContent());
notificationBuilder.setOngoing(true);
notificationBuilder.setTicker("Hello");
notificationBuilder.setSmallIcon(R.drawable.notif_icon);
mNotificationManager.notify(R.id.notification_layout, notificationBuilder.build());
}
private RemoteViews getNotificationContent() {
RemoteViews notificationContent = new RemoteViews(getPackageName(), R.layout.keyphrase_recogniser_notification);
notificationContent.setTextViewText(R.id.notification_title, "title");
notificationContent.setTextViewText(R.id.notification_subtitle, "subtitle");
return notificationContent;
}
This is a broad guide, if you need more specific code let us know.

Categories

Resources