I am sending push notification message from Firebase console to my app running on emulator.
The MyFirebaseMessagingService class looks like this:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
if(remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
if(remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
Intent intent = new Intent(this, SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "my_channel_01");
notificationBuilder.setContentTitle("FCM Notification");
notificationBuilder.setContentText(remoteMessage.getNotification().getBody());
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
notificationBuilder.setContentIntent(pendingIntent);
notificationBuilder.setChannelId("my_channel_01");
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
The constructor for NotificationCompat.Builder for API 26 now takes two params one is Context and another is String channelId. So I just assigned a random string to my channel.
But when I send the message from the firebase console the app on emulator gives me an error TOAST saying:
Failed to post notification on channel "my_channel_01"
What am I doing wrong?
When your build specifies a targetSdkVersion of 26, and you run on an API level 26 device or emulator, you must both specify a channel ID when constructing NotificationCompat.Builder, and also create the channel.
You could use a method like this:
public static final String NOTIF_CHANNEL_ID = "my_channel_01";
...
#RequiresApi(Build.VERSION_CODES.O)
private void createNotifChannel(Context context) {
NotificationChannel channel = new NotificationChannel(NOTIF_CHANNEL_ID,
"MyApp events", NotificationManager.IMPORTANCE_LOW);
// Configure the notification channel
channel.setDescription("MyApp event controls");
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = context.getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
Log.d(TAG, "createNotifChannel: created=" + NOTIF_CHANNEL_ID);
}
And because it is only needed for API 26 and requires that level, invoke it like this:
// The channel need only be created for API 26 devices. For devices
// running an API less the 26, there is no way to create a channel and the
// channel ID specified in the constuctor to NotificationCompat.Builder is
// merely a placeholder.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotifChannel(this);
}
It does no harm to recreate the NotificationChannel, which provides some flexibility in where you do it. If your app has multiple entry points (activity, broadcast receiver, etc) take care to ensure the channel is created for all cases. You can also ensure it is only created once using NotificationManager.getNotificationChannel():
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (manager.getNotificationChannel(NOTIF_CHANNEL_ID) == null) {
createNotifChannel(this);
}
}
Related
I'm sending notification using a firebase cloud function. When I'm sending the payload with notification key, notification sends but method not invoked. But with data key, nothing happened.
Here is my code for FirebaseMessagingService
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
sendNotification(remoteMessage.getData().get("title"), remoteMessage.getData().get("body"));
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
}
}
private void sendNotification(String title, String messageBody){
String channelId = getString(R.string.default_notification_channel_id);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
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, channelId)
.setSmallIcon(R.drawable.ic_logo)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 , notificationBuilder.build());
}
Here is my firebase cloud function
exports.sendNotification = functions.database
.ref("/deals/{userId}/{dealId}")
.onCreate((data, context) => {
const dataValue = data.val();
const topic = context.params.userId;
const payload = {
data: {
title: "New deal created",
body: dataValue.user.name + " added a new deal."
},
topic: topic
};
// Send a message to devices subscribed to the provided topic.
return admin
.messaging()
.send(payload)
.then(response => {
// Response is a message ID string.
console.log("Successfully sent message:", response);
})
.catch(error => {
console.log("Error sending message:", error);
});
});
Also I set up a debugpoint on onMessageReceived() but it did not get fired up.
I figured out the problem. The issue is after doing some changes and building the android project we need to subscribe to topic again.
When your app is in background , firebase will not trigger
OnMessageReceived instead it will show a notification alert
+
make sure you have subscribed the correct topic
+
make sure play services are updated on your device.
This is my first question. I have connected my domain into firebase. The push notification is working when I update the post in my Wordpress Blog. Ok, thats good for now. But, i want to save all that notification in a Fragment, and can be clicked from there to start an activity for post id. How to save that Notification?
Here is my Firebase Messaging code:
private static int VIBRATION_TIME = 500; // in millisecond
private SharedPref sharedPref;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
sharedPref = new SharedPref(this);
if (sharedPref.getNotification()) {
// play vibration
if (sharedPref.getVibration()) {
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(VIBRATION_TIME);
}
RingtoneManager.getRingtone(this, Uri.parse(sharedPref.getRingtone())).play();
if (remoteMessage.getData().size() > 0) {
Map<String, String> data = remoteMessage.getData();
FcmNotif fcmNotif = new FcmNotif();
fcmNotif.setTitle(data.get("title"));
fcmNotif.setContent(data.get("content"));
fcmNotif.setPost_id(Integer.parseInt(data.get("post_id")));
displayNotificationIntent(fcmNotif);
}
}
}
private void displayNotificationIntent(FcmNotif fcmNotif) {
Intent intent = new Intent(this, ActivitySplash.class);
if (fcmNotif.getPost_id() != -1) {
intent = new Intent(this, ActivityPostDetails.class);
Post post = new Post();
post.title = fcmNotif.getTitle();
post.id = fcmNotif.getPost_id();
boolean from_notif = !ActivityMain.active;
intent.putExtra(ActivityPostDetails.EXTRA_OBJC, post);
intent.putExtra(ActivityPostDetails.EXTRA_NOTIF, from_notif);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(fcmNotif.getTitle());
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(fcmNotif.getContent()));
builder.setContentText(fcmNotif.getContent());
builder.setSmallIcon(R.drawable.ic_notification);
builder.setDefaults(Notification.DEFAULT_LIGHTS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder.setPriority(Notification.PRIORITY_HIGH);
}
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int unique_id = (int) System.currentTimeMillis();
notificationManager.notify(unique_id, builder.build());
}
}
yes you can store the your Notification payload in database and create list in fragment and show data from Database and click on any row start activity according to Post ID by getting post id by position
You can save notification message when the notificaton arrived inside
onMessageReceived(RemoteMessage remoteMessage)
method like this
A full example of a notification is like this..
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* 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) {
try {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
// TODO(developer): Handle FCM messages here.
Map<String, String> data = remoteMessage.getData();
String value1 = data.get("key_1");
String value2 = data.get("key_2");
String title=data.get("title");
String msg=data.get("body");
Log.d("Backgraound", value1);
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// 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(title,msg,value1,value2);
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
private void sendNotification(String title,String messageBody, String val1,String val2) {
try {
Intent intent = new Intent(this, Notification_activity.class);
//Bundle bundle = getApplicationContext().getExtras();
Bundle basket = new Bundle();
basket.putString("key_1", val1);
basket.putString("key_2", val2);
intent.putExtras(basket);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.spacebar_round)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setColor( getResources().getColor(R.color.colorPrimary))
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher));
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
}
I am sending some push notifications to android from AWS,
the notification process is working registering the device, and I indeed get the test notifications, but only showing on the log, not on notification bar on top of the screen like any other notification would...
public void onMessageReceived(RemoteMessage remoteMessage) {
// ...
// TODO(developer): Handle FCM messages here.
Log.d("mako", "A From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d("mako", "B Message data payload: " + remoteMessage.getData());
if (/* Check if data needs to be processed by long-running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
// scheduleJob();
} else {
// Handle message within 10 seconds
// handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d("mako", "C Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// 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.
}
So, I send a test notification:
{
"GCM": "{ \"data\": { \"message\": \"test message\" } }"
}
And I can see in my console log the message test:
10-05 14:57:08.827 23062-23296/com.sb.comm D/mako: B Message data payload: {message=test message}
But is not showing on the little pop-up, What is missing to show the actual push notification on the screen?
Cheers
You have to Generate Notification on your device like this
public void onMessageReceived(RemoteMessage remoteMessage) {
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("App Name")
.setBadgeIconType(R.drawable.ic_notification)
.setLargeIcon(BitmapFactory.decodeResource(
getResources(),R.drawable.ic_notification))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentText(remoteMessage.getData().get("body"));
NotificationManager notificationManager =
(NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(141, notificationBuilder.build());
}
Here Notification Builder will get data from your server notification payload and generate a notification on device.
please add these lines of code to show notification on notification bar.
Intent intent = new Intent(this, YourActivity.class);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new
NotificationCompat.Builder(this, "my_chanel_id");
notificationBuilder.setSmallIcon(R.drawable.ic_launcher_app);
notificationBuilder.setContentTitle("Titlee");
notificationBuilder.setContentText("anyText");
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSound(uri);
notificationBuilder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String CHANNEL_ID = "my_channel_01";// The id of the channel.
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel("mychanelId",
"hyperlocal", importance);
notificationManager.createNotificationChannel(mChannel);
}
notificationManager.notify(message_id, notificationBuilder.build());
Turns out it was to do with the formatting of the body, it is not as suggested by >>> SNS "JSON message generator"
the body should be in this format:
{
"GCM": "{ \"notification\": { \"text\": \"test message\" } }"
}
I am developing an app that works with FirebaseMessagingService and NotificationCompat. My target API is 26. The problem I have is that notifications in android 7.1.1 appear and close at once, they are not kept in the notification bar. However, in Android 7.0 it works perfectly. I saw many tutorials and in all they do the same thing that I do. I would like to know what I may be missing.
My Services
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Map data = remoteMessage.getData();
if (SinchHelpers.isSinchPushPayload(data)) {
//comentario
} else {
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload => " + remoteMessage.getData());
Map<String, String> params = remoteMessage.getData();
JSONObject object = new JSONObject(params);
try {
sendNotification(object.get("message").toString(), object.get("chatId").toString(), object.get("user").toString());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG, "JSONException => " + e.getMessage());
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body => " + remoteMessage.getNotification().getBody());
}
}
}
}
private void sendNotification(String messageBody, String chatId, String userName) {
try {
Intent intent = new Intent(this, ChatActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXTRA_CHAT_ID", chatId);
intent.putExtra("EXTRA_USER", userName);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent, PendingIntent.FLAG_ONE_SHOT);
String channelId = "fcm_default_channel";
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher_foreground)
.setContentTitle(userName)
.setContentText(messageBody)
.setAutoCancel(true)
.setGroup(userName)
.setSound(defaultSoundUri)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
} catch (Exception e) {
Log.e(TAG, "userName => " + userName + " => " + e.getMessage());
}
}
Notification channels: Android 8.0 introduces notification channels that allow you to create a user-customizable channel for each type of notification you want to display.
Please have a look at the documentation.
Build a notification.
I'm getting a weird crash report from Crashlytics saying that my app has crashed because of a Toast message not called from the UI thread. It's weird because I don't show Toast messages from push notifications. It looks like it's working for thousands of different users, but for this one is crashing. I don't know what's going on. Below is the report:
Fatal Exception: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.(Handler.java:209)
at android.os.Handler.(Handler.java:123)
at android.widget.Toast$TN.(Toast.java:350)
at android.widget.Toast.(Toast.java:106)
at android.widget.Toast.makeText(Toast.java:264)
at android.media.RingtoneManager.isRingtoneExist(RingtoneManager.java:1195)
at android.app.NotificationManager.notify(NotificationManager.java:235)
at com.google.firebase.messaging.zza.zzt(Unknown Source)
at com.google.firebase.messaging.FirebaseMessagingService.handleIntent(Unknown Source)
at com.google.firebase.iid.zzc.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
app dependencies:
implementation 'com.google.firebase:firebase-core:12.0.1'
implementation 'com.google.firebase:firebase-messaging:12.0.1'
Device: Android 6.0 - Alcatel Shine Lite 5080X
The firebase push service:
public class FirebasePushService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(App.NAME, "message received");
Map<String, String> map = remoteMessage.getData();
JSONObject json = new JSONObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
json.put(key, value);
}
int pushType = json.getInt("push_type", -1);
if (pushType > 0) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_ONE_SHOT);
createNotification();
}
}
private void createNotification() {
// create the channel first
createChannels();
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Build b = new NotificationCompat.Builder(context, CHANNEL_ID)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setSound(defaultSoundUri)
.setColor(ContextCompat.getColor(context, R.color.primaryColor));
b.setContentIntent(pi);
b.setAutoCancel(true);
Notification not = b.build();
not.flags |= Notification.FLAG_AUTO_CANCEL;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
not.ledARGB = Color.GREEN;
not.flags = Notification.FLAG_SHOW_LIGHTS;
not.ledOnMS = 1000;
not.ledOffMS = 1000;
not.defaults |= Notification.DEFAULT_VIBRATE;
not.defaults |= Notification.DEFAULT_SOUND;
}
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(PUSH_NOTIFICATION_ID, not);
}
#TargetApi(Build.VERSION_CODES.O)
private void createChannels() {
// create android channel
NotificationChannel androidChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
// Sets whether notifications posted to this channel should display notification lights
androidChannel.enableLights(true);
// Sets whether notification posted to this channel should vibrate.
androidChannel.enableVibration(true);
// Sets the notification light color for notifications posted to this channel
androidChannel.setLightColor(Color.GREEN);
// Sets whether notifications posted to this channel appear on the lockscreen or not
androidChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
getManager().createNotificationChannel(androidChannel);
}
}
Does anyone have any clue what's going on?