This question already has answers here:
Notification not showing in Oreo
(24 answers)
Closed 4 years ago.
I am setting up firebase push notification, and as per the documentation I did everything I guess
So what I did is from Tools > Firebase > Cloud Messaging added Dependencies see my gradle
implementation 'com.google.firebase:firebase-core:11.8.0'
implementation 'com.google.firebase:firebase-messaging:11.8.0'
implementation 'com.google.android.gms:play-services-ads:11.8.0'
After this I created a Class MyyFirebaseMessagingService and extended FirebaseMessagingService see below
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d("RefreshedToken", "onMessageReceived: " + remoteMessage.getNotification().getBody());
showNotification(remoteMessage.getNotification().getBody());
}
private void showNotification(String message) {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.logo)
.setContentTitle("Quotes App")
.setContentText(message)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, notification);
}}
After this I addeed Service in the manifest
<service
android:name=".MyFirebaseMessagingService"
android:enabled="true"
android:exported="true"
>
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
And now when I try to send notification I dont receive it. What am I doing wrong
Create a channel and set the importance
Before you can deliver the notification on Android 8.0 and higher, you
must register your app's notification channel with the system by
passing an instance of NotificationChannel to
createNotificationChannel().
As the documentation say, you need to add a notification channel in android 8 and higher so the system shows your notification.
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
First of all, you need to create notification channel...and channel id should be between 1 to 10.
Secondly, upgrade to the latest version of libraries in app/gradle.build
If app is in the foreground (visible to user), onMessageReceived() is called.
If app is in the background (not visible to user), then, onMessageReceived() isn't called and notification is automatically shown to user, without you manually showing them...and data values are passed as intent extras to you launcher activity when clicked.
Related
im referring this answer for foreground and background to receive firebase notification
--> https://stackoverflow.com/a/38451582/12553303
actually following is my doubt:----------
what if i didnt code for foreground condition(talking about push notification) still i will get notifcation when my app is in background right????-->yes
but when im on foreground state and i pushed a notification from firebase -->i wont see notification on status bar that is also okay(beacuse suppose i didnt override onmessagereceive() method)....then next i go to background state i didnt see any notification though which i sent for background
what should i do to get notification which i sent for background like going from foreground state(with no method of onmessagereceived()) to
background state??*
thanks need advice and clarification on this ...
is this even possible get that notification moving from foreground state to
background state??
code :----
override fun onMessageReceived(p0: RemoteMessage) {
super.onMessageReceived(p0)
Log.d("msg", "onMessageReceived: " + p0.getData().get("message"))
val intent = Intent(this, OrderListActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
val channelId = "Default"
val builder: NotificationCompat.Builder =NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(p0.getNotification()?.getTitle())
.setContentText(p0.getNotification()?.getBody()).setAutoCancel(true)
.setContentIntent(pendingIntent)
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId,
"Default channel",
NotificationManager.IMPORTANCE_DEFAULT)
manager.createNotificationChannel(channel)
}
manager.notify(0, builder.build())
}
any advice will be appreciated thanks
To receive messages in an Android app, Firebase Notifications contains different mechanisms when app is foreground or in background.
When the app is closed, your notifications are processed by the Google Service process, which display your notifications as required, including click action i.e.opening the app and the notification icon.
When the app is in foreground, the received messages are processed by the app.
To fix this, following are the steps to follow:-
1.Create a new class that extends FirebaseMessagingService
2.Implement the onMessageReceived() method
3.Then get the Notification object from the remoteMessage and create your own Android Notification like,
public class MyNotificationService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(remoteMessage.getNotification().getTitle())
.setContentText(remoteMessage.getNotification().getBody())
.setSmallIcon(R.mipmap.ic_launcher)
.build();
NotificationManagerCompat manager = NotificationManagerCompat.from(getApplicationContext());
manager.notify(1, notification);
}
}
4.Then add the Service in your AndroidManifest.xml
<service android:name=”.MyNotificationService”>
<intent-filter>
<action android:name=”com.google.firebase.MESSAGING_EVENT”/>
</intent-filter>
</service>
Hopefully I am phrasing this correctly, but does Android provide a standard mechanism (such as a popup or banner) to display notifications when inside the application? The notifications will be sent to the device via FireBase, once I receive the Notification in the FireBase service onMessageReceived() I want to then display the notification inside the App, so the user can then either let the notice disappear or can react to it (bringing them somewhere else in the application).
So in the Firebase messaging service I want to react to the notification based on the data passed in (I know this will only work with the App in the foreground, but I have implemented other code to handle it in the Intent from the system tray):
public class MyCompanyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
// Do a popup or something to alert the user and then allow them to move to that activity
}
}
Is there a pattern or standard way to do this in Android or is this something I need to code myself? I can't seem to find any reference to it in the Android documentation.
Also, how would this relate to Notification Channels?
Refer to an example here: https://demonuts.com/firebase-cloud-messaging-android/
Follow the method private void generateNotification(String messageBody) in the post.
Starting from Android O and onwards, it is necessary to post the notification in a notification channel. A notification channel helps to group the notification that our app sends.
So in the above post where u create the notification using NotificationCompat.Builder just call method setChannel() and set the created channel. Highlevel steps would be-
Create Notification channel:
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "some_channel_id";
CharSequence channelName = "Some Channel";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel notificationChannel = new
NotificationChannel(channelId, channelName, importance);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500,
400, 300, 200, 400});
notificationManager.createNotificationChannel(notificationChannel);
Create Notification and set channel
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int notifyId = 1;
String channelId = "some_channel_id";
Notification notification = new Notification.Builder(MainActivity.this)
.setContentTitle("Some Message")
.setContentText("You've received new messages!")
.setSmallIcon(R.drawable.ic_notification)
.setChannel(channelId)
.build();
notificationManager.notify(id, notification);
Additionally for a detailed description on notification channel follow https://medium.com/exploring-android/exploring-android-o-notification-channels-94cd274f604c
I need to generate notifications when a PUSH notification is received but also I need to generate notifications (for display them in the notification bar of the device) when something happens in the application, so I'm using NotificationCompat.Builder for it.
As you know, android has deprecated this call to Notification.Builder:
Notification.Builder (Context context)
And now you must use this call:
NotificationCompat.Builder (Context context, String channelId)
What happens if you don't want to specify a notification channel and you want to send general notifications to all the users of your app and you want to receive all the notifications in all the apps installed without dealing with notification channels? Or what happens if you want to create a simple notification in the notification bar when a user has pressed a button in your app? How to display a notification without specifying the channelId? I mean... just working like until api 26 and before notification channels appeared.
Can't see how to work without specifying notification channels in any place of the official documentation.
Notification Channels are mandatory on Android 8+. So you must use NotificationCompat.Builder(Context context, String channelId) and create channel(s) on api 26+ via NotificationManager.createNotificationChannel(NotificationChannel channel).
On api < 26, just don't call createNotificationChannel but let the channel id parameter (just a String).
val builder = NotificationCompat.Builder(context, "a_channel_id")
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_notif)
.setAutoCancel(true)
...
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.notify(NOTIFICATION_ID, builder.build())
on Api 26+, create a channel before:
val channel = NotificationChannel("a_channel_id", "channel_name", NotificationManager.IMPORTANCE_HIGH)
channel.description = "channel_description"
channel.enableLights(true)
channel.lightColor = Color.RED
channel.enableVibration(true)
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.createNotificationChannel(channel)
There is currently no workaround for this. Notification Channels has been recently announced (last last I/O if I remember correctly), and is (most probably if not absolutely) here to stay. What I do though is something like this.
To abide to the new standard, I just implement the Notification Channels, but only as needed. I also use FCM on my app and here's something similar to what I have for it -- this is in my Application class:
private void initFirebase() {
... // other Firebase stuff.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) initNotificationChannels();
}
#TargetApi(Build.VERSION_CODES.O)
private void initNotificationChannels() {
NotificationChannel publicChannel = new NotificationChannel(NOTIFICATION_CHANNEL_PUBLIC,
NOTIFICATION_CHANNEL_PUBLIC, NotificationManager.IMPORTANCE_DEFAULT);
publicChannel.setDescription(NOTIFICATION_CHANNEL_PUBLIC);
NotificationChannel privateChannel = new NotificationChannel(NOTIFICATION_CHANNEL_PRIVATE,
NOTIFICATION_CHANNEL_PRIVATE, NotificationManager.IMPORTANCE_HIGH);
publicChannel.setDescription(NOTIFICATION_CHANNEL_PRIVATE);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (mNotificationManager != null) {
mNotificationManager.createNotificationChannel(publicChannel);
mNotificationManager.createNotificationChannel(privateChannel);
}
}
And my MessagingService has something like this:
private static final String NOTIFICATION_CHANNEL_PRIVATE = "my.app.package.name.private";
private static final String NOTIFICATION_CHANNEL_PUBLIC = "my.app.package.name.public";
private void buildNotification(....(other params),String source, String message) {
String channelId = getChannelId(source);
Intent resultIntent = new Intent(this, MyActivity.class);
resultIntent.putExtra(EXTRAS_PARAM_ID, myVal);
PendingIntent notificationIntent = buildNotificationIntent(channelId, roomId, roomType);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, getChannelId(source))
.setSmallIcon(R.drawable.ic_sample
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_SOUND)
.setContentIntent(notificationIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id, 0, notificationBuilder.build());
}
private String getChannelId(String source) {
switch(source){
case PRIVATE:
return NOTIFIFICATION_CHANNEL_PRIVATE;
default:
return NOTIFICATION_CHANNEL_PUBLIC;
}
}
I don't know if this answers the question or not. But, having any channel below api 26 just worked without doing anything on my app.
1. instantiate notificationCompat with some channel Id
//which is irrelevant for api < 26
2. handle the case of creating notification channel for api 26+
3. bundled it up.
It just worked. Configuring Notifications did not have any effects below api 26.
I use fcm and heads up notification will show when app is open but not show when app is not open or killed.
How to handle heads up notification when app is not open?
Doc say :
With Android 5.0 (API level 21), notifications can appear in a small
floating window (also called a heads-up notification) when the device
is active (that is, the device is unlocked and its screen is on).
These notifications appear similar to the compact form of your
notification, except that the heads-up notification also shows action
buttons. Users can act on, or dismiss, a heads-up notification without
leaving the current app.
As per Doc, If you want heads-up notification you have to create your own as below :
notificationBuilder.setPriority(Notification.PRIORITY_HIGH);
if (Build.VERSION.SDK_INT >= 21) notificationBuilder.setVibrate(new long[0]);
Don't abuse heads-up notification. See here for when to use heads-up notification:
MAX: For critical and urgent notifications that alert the user to a
condition that is time-critical or needs to be resolved before they
can continue with a particular task.
HIGH: Primarily for important communication, such as messages or chat
events with content that is particularly interesting for the user.
High-priority notifications trigger the heads-up notification display.
Additional note from HERE
Update :
To override GCM listener service :
<service android:name=".MyGcmListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
FCM would be :
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
Then override method :
GCM :
public class MyGcmListenerService
extends GcmListenerService {
#Override
public void onMessageReceived(String from, Bundle data) {
... create your heads-up notification here.
}
FCM :
public class MyFirebaseMessagingService extends FirebaseMessagingService {
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
... create your heads-up notification here.
}
Can't post in comment, so here it is. Try this, i had tested :
private void test() {
Intent intent;
intent = new Intent(this, SplashScreenActivity.class);
Bundle bundle = new Bundle();
bundle.putBoolean("isDisplayAlert", true);
bundle.putString("NOTIFICATION_DATA", "data");
intent.putExtras(bundle);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
new Random().nextInt(), intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_location)
.setContentTitle("Title")
.setContentText("Body")
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setOnlyAlertOnce(true)
.setFullScreenIntent(pendingIntent, true);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder.setPriority(Notification.PRIORITY_HIGH);
notificationBuilder.setVibrate(new long[0]);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
Yesterday Google presented at Google I/O the new notification system based on the new Firebase. I tried this new FCM ( Firebase Cloud Messaging ) with the example on Github.
The icon of the notification is always the ic_launcher despite I have declared a specific drawable
Why ?
Here below the official code for handling the message
public class AppFirebaseMessagingService extends FirebaseMessagingService {
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// If the application is in the foreground handle both data and notification messages here.
// 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.
sendNotification(remoteMessage);
}
// [END receive_message]
/**
* Create and show a simple notification containing the received FCM message.
*
* #param remoteMessage FCM RemoteMessage received.
*/
private void sendNotification(RemoteMessage remoteMessage) {
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);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
// this is a my insertion looking for a solution
int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.myicon: R.mipmap.myicon;
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(icon)
.setContentTitle(remoteMessage.getFrom())
.setContentText(remoteMessage.getNotification().getBody())
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
Unfortunately this was a limitation of Firebase Notifications in SDK 9.0.0-9.6.1. When the app is in the background the launcher icon is use from the manifest (with the requisite Android tinting) for messages sent from the console.
With SDK 9.8.0 however, you can override the default! In your AndroidManifest.xml you can set the following fields to customise the icon and color:
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/notification_icon" />
<meta-data android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/google_blue" />
Note that if the app is in the foreground (or a data message is sent) you can completely use your own logic to customise the display. You can also always customise the icon if sending the message from the HTTP/XMPP APIs.
Use a server implementation to send messages to your client and use data type of messages rather than notification type of messages.
This will help you get a callback to onMessageReceived irrespective if your app is in background or foreground and you can generate your custom notification then
atm they are working on that issue https://github.com/firebase/quickstart-android/issues/4
when you send a notification from the Firebase console is uses your app icon by default, and the Android system will turn that icon solid white when in the notification bar.
If you are unhappy with that result you should implement FirebaseMessagingService and create the notifications manually when you receive a message. We are working on a way to improve this but for now that's the only way.
edit: with SDK 9.8.0 add to AndroidManifest.xml
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="#drawable/my_favorite_pic"/>
My solution is similar to ATom's one, but easier to implement. You don't need to create a class that shadows FirebaseMessagingService completely, you can just override the method that receives the Intent (which is public, at least in version 9.6.1) and take the information to be displayed from the extras. The "hacky" part is that the method name is indeed obfuscated and is gonna change every time you update the Firebase sdk to a new version, but you can look it up quickly by inspecting FirebaseMessagingService with Android Studio and looking for a public method that takes an Intent as the only parameter. In version 9.6.1 it's called zzm.
Here's how my service looks like:
public class MyNotificationService extends FirebaseMessagingService {
public void onMessageReceived(RemoteMessage remoteMessage) {
// do nothing
}
#Override
public void zzm(Intent intent) {
Intent launchIntent = new Intent(this, SplashScreenActivity.class);
launchIntent.setAction(Intent.ACTION_MAIN);
launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* R equest code */, launchIntent,
PendingIntent.FLAG_ONE_SHOT);
Bitmap rawBitmap = BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(rawBitmap)
.setContentTitle(intent.getStringExtra("gcm.notification.title"))
.setContentText(intent.getStringExtra("gcm.notification.body"))
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
if your app is in background the notification icon will be set onMessage Receive method but if you app is in foreground the notification icon will be the one you defined on manifest
Just set targetSdkVersion to 19. The notification icon will be colored.
Then wait for Firebase to fix this issue.
There is also one ugly but working way. Decompile FirebaseMessagingService.class and modify it's behavior. Then just put the class to the right package in yout app and dex use it instead of the class in the messaging lib itself. It is quite easy and working.
There is method:
private void zzo(Intent intent) {
Bundle bundle = intent.getExtras();
bundle.remove("android.support.content.wakelockid");
if (zza.zzac(bundle)) { // true if msg is notification sent from FirebaseConsole
if (!zza.zzdc((Context)this)) { // true if app is on foreground
zza.zzer((Context)this).zzas(bundle); // create notification
return;
}
// parse notification data to allow use it in onMessageReceived whe app is on foreground
if (FirebaseMessagingService.zzav(bundle)) {
zzb.zzo((Context)this, intent);
}
}
this.onMessageReceived(new RemoteMessage(bundle));
}
This code is from version 9.4.0, method will have different names in different version because of obfuscation.
write this
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_notification" />
right down <application.....>
I'm triggering my notifications from FCM console and through HTTP/JSON ... with the same result.
I can handle the title, full message, but the icon is always a default white circle:
Notification screenshot
Instead of my custom icon in the code (setSmallIcon or setSmallIcon) or default icon from the app:
Intent intent = new Intent(this, MainActivity.class);
// use System.currentTimeMillis() to have a unique ID for the pending intent
PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
if (Build.VERSION.SDK_INT < 16) {
Notification n = new Notification.Builder(this)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pIntent)
.setAutoCancel(true).getNotification();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//notificationManager.notify(0, n);
notificationManager.notify(id, n);
} else {
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
Notification n = new Notification.Builder(this)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setLargeIcon(bm)
.setContentIntent(pIntent)
.setAutoCancel(true).build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//notificationManager.notify(0, n);
notificationManager.notify(id, n);
}
Thought I would add an answer to this one, since my problem was simple but hard to notice. In particular I had copy/pasted an existing meta-data element when creating my com.google.firebase.messaging.default_notification_icon, which used an android:value tag to specify its value. This will not work for the notification icon, and once I changed it to android:resource everything worked as expected.