I am making MQTT client app using paho MQTT client dependency.
Implementing code in a Background Service. and everything works well except the Notification isn't working!
Service code snippet is here:
My Codes occurs inside the TimeDisplayTimerTask inner-class.
This code located at the callback function :
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
mIntent = new Intent(getApplicationContext(), MainActivity.class);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, mIntent, 0);
createNotificationChannel();
Toast.makeText(getApplicationContext(),"A message received : "+ new String(message.getPayload()),Toast.LENGTH_SHORT).show();
vibrator.vibrate(500);
myRingtone.play();
mBuilder .setContentTitle("Message received at : " + mTopic)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setContentText("Message : "+ new String(message.getPayload()));
mNotificationManager.notify(0, mBuilder.build());
}
And this code creates a notification channel (as Google developers guide mentioned to write):
Posted with help of this answer.
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String chanel_id = "3000";
CharSequence name = "Mqtt message";
String description = "Message arrived";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel mChannel = new NotificationChannel(chanel_id, name, importance);
mChannel.setDescription(description);
mChannel.enableLights(true);
mChannel.setLightColor(Color.BLUE);
mNotificationManager = getSystemService(NotificationManager.class);
if (mNotificationManager != null) {
mNotificationManager.createNotificationChannel(mChannel);
}
mBuilder = new NotificationCompat.Builder(getApplicationContext(), chanel_id);
}
else
{
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(getApplicationContext());
}
}
When it receives a message, A toast message appears holding the message.
But it doesn't push notification.
Checked Apps and Notifications, All notifications are allowed.
SOLVED :
the setter method .setSmallIcon must be called to successfully build a notification.
Which was not important to me.
Related
We have created an chat app with notifications using FCM my code is correct my device is getting the push notification data as well but some Chinese manufactured device like vivo, oppo, one plus, xiaomi are not allowing the notification to show unless i add app in protected app list of respective manufacturer. is their any solution for this.
https://hackernoon.com/notifications-in-android-are-horribly-broken-b8dbec63f48a
https://github.community/t5/Project-Development-Help-and/Firebase-Push-Notification-not-receiving-on-some-android-devices/td-p/5489
private NotificationManagerCompat notificationManager;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d("test","call");
notificationManager = NotificationManagerCompat.from(this);
sendNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody());
}
private void sendNotification(String title, String msg) {
Intent resultIntent = new Intent(this, ActivitySplashScreen.class);
String channelId = getString(R.string.chc);
String channelName = "Message Notification";
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(resultIntent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(99, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(title)
.setContentText(msg)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentIntent(pendingIntent)
.build();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager manager = getSystemService(NotificationManager.class);
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
}
notificationManager.notify(10, notification);
}
I can confirm that this implementation works well with One Plus and Xiaomi devices (we have plenty of users using our app from this devices, and no crashes or issues are created from them regarding FCM Notifications).
Cannot confirm anything for Vivo or Oppo (so far, we do know we don't have users using this kind of devices).
The most important thing is that the notification feature is well implemented if regarding the app is either in foreground or background. If someone wants to do a zoom on this matter, this article explains it on a easy way.
Now, the code I use for FCM implementation in Android:
//MyMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static final String TAG = "Firebase Msg";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
final LocalNotification localNotification = new LocalNotification();
//data --> entityId - entityType - pushNotificationType
// Check if message contains a data payload.
if (data.size() > 0) {
localNotification.setEntityId(data.get("entityId"));
localNotification.setEntityType(data.get("entityType"));
localNotification.setPushNotificationType(data.get("pushNotificationType"));
localNotification.setTitle(data.get("title"));
localNotification.setBody(data.get("body"));
localNotification.setIcon(data.get("icon"));
localNotification.setDate(new Date().getTime());
localNotification.setRead(false);
}
if (localNotification.getEntityId() != null) {
LocalNotification notificationRetrieved = FirebaseNotificationsHelper.insertLocalNotification(localNotification);
FirebaseNotificationsHelper.createNotificationInStatus(notificationRetrieved);
}
}
}
//Create notification status
static void createNotificationInStatus(LocalNotification localNotification) {
String notificationChannelId = App.getContext().getString(R.string.default_notification_channel_id);
String notificationChannelName = App.getContext().getString(R.string.default_notification_channel_name);
String notificationChannelDescription = App.getContext().getString(R.string.default_notification_channel_description);
NotificationCompat.Builder notificationBuilder;
NotificationCompat.Builder notificationBuilderPublicVersion;
notificationBuilder = new NotificationCompat.Builder(App.getContext(), notificationChannelId);
notificationBuilderPublicVersion = new NotificationCompat.Builder(App.getContext(), notificationChannelId);
notificationBuilder.setDefaults(NotificationCompat.DEFAULT_VIBRATE | NotificationCompat.DEFAULT_LIGHTS | NotificationCompat.DEFAULT_SOUND)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.ic_stat_push_notif)
.setTicker(localNotification.getTitle())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentTitle(localNotification.getTitle())
.setContentText(localNotification.getBody())
.setStyle(new NotificationCompat.BigTextStyle().bigText(localNotification.getBody()))
.setPublicVersion(notificationBuilderPublicVersion.setSmallIcon(R.drawable.ic_stat_push_notif).setContentTitle(localNotification.getTitle()).
setWhen(System.currentTimeMillis()).setContentText(localNotification.getBody()).build())
.setGroup(NOTIFICATION_GROUP)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setAutoCancel(true);
int notificationId = SharedPreferencesUtils.getInstance(App.getContext()).getIntValue(PREF_KEY_NOTIFICATION_ID, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) App.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel(notificationChannelId, notificationChannelName, NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription(notificationChannelDescription);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC);
notificationChannel.setImportance(NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(notificationId, notificationBuilder.build());
} else {
/* Kitkat and previous versions don't show notifications using NotificationManagerCompat */
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
NotificationManager notificationManager = (NotificationManager) App.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, notificationBuilder.build());
} else {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(App.getContext());
notificationManager.notify(notificationId, notificationBuilder.build());
}
}
notificationId++;
SharedPreferencesUtils.getInstance(App.getContext()).setValue(PREF_KEY_NOTIFICATION_ID, notificationId);
}
I donot think that there is a general solution for this since your app is based on google-FCM that means that the android device regularly comunicates with google-internet-services.
As far as i know google-FCM is blocked (= not reachable) in china
I am working on an app where i am using custom Push Notification whenever there is an update from server that we need to send the notification, i am sending the notification using Notification builder and everything is working as expected, and i am redirecting the user to the relevant post on the ViewPager by mapping the Heading of the Notification.
I am attaching the code i am using
Notification Builder code
Intent resultIntentArticle = new Intent(context, HomeActivity.class);
resultIntentArticle.putExtra("pushNotificationClick", "yes");
resultIntentArticle.putExtra("heading", allArticles.get(0).getArticleHeading().trim());
resultIntentArticle.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent resultPendingIntent = PendingIntent.getActivity(context,
0, resultIntentArticle,
PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder = new NotificationCompat.Builder(context);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mBuilder.setSmallIcon(R.mipmap.icon_not);
} else {
mBuilder.setSmallIcon(R.mipmap.icon_not);
}
mBuilder.setColor(getResources().getColor(R.color.colorPrimary));
mBuilder.setContentTitle("" + allArticles.get(0).getArticleHeading().trim())
.setContentText("" + allArticles.get(0).getArticleContent().trim())
.setAutoCancel(true)
.setContentIntent(resultPendingIntent);
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
notificationChannel.enableLights(true);
assert mNotificationManager != null;
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify((int) System.currentTimeMillis() /* Request Code */, mBuilder.build());
currentNotificationStatus = "sent";
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit().putString("currentNotificationStatus" +
"", "" + currentNotificationStatus).apply();
I am sending two variables with PendingIntent i.e. pushNotificationClick and heading and am recieving it inside my Activity like this.
notificationClickedStatus = getIntent().getStringExtra("pushNotificationClick");
notificationHeading = getIntent().getStringExtra("heading");
Now the problem is that whenever we get 2-3 notifications and the user clicked on the very first notification that i have got, i am still getting the latest Notification heading in my activity. Earlier it was working completely fine, but now i am not getting any clue.
I am implementing firebase push notification in my app, the app is showing the push notification also. But my problem is - I may send different types of push notifications based on different topics.
Ex -
1. If I am sending a push notification on App Update, then on clicking that notification by the user, he should be redirected to PlayStore
If I am sending a push notification on New Contents, then on clicking that notification by the user, he should be redirected to App's MainActivity
If I am sending a push notification on New Contest, then on clicking that notification by the user, he should be redirected to App's ContestActivity
I implemented it using the below code in "MessageReceiver" class as --
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String title = remoteMessage.getNotification().getTitle();
String message = remoteMessage.getNotification().getBody();
showNotifications(title, message);
}
private void showNotifications(String title, String msg) {
Intent i = null;
if(title.equals("DoUp Now - Update")){
Uri uri = Uri.parse("https://play.google.com/store/apps/details?id=com.s2s.doupnow"); // missing 'http://' will cause crashed
i = new Intent(Intent.ACTION_VIEW, uri);
}
else if(title.equals("DoUp Now - New Content")){
i = new Intent(this, MainActivity.class);
}
else if(title.equals("DoUp Now - New Notification")){
i = new Intent(this, NotificationActivity.class);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, REQUEST_CODE,
i, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder, mBuilderOld;
final int NOTIFICATION_ID = 1;
final String NOTIFICATION_CHANNEL_ID = "my_notification_channel";
mNotifyManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
mNotifyManager.createNotificationChannel(notificationChannel);
mBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
mBuilder.setContentTitle(title)
.setContentText(msg)
.setSmallIcon(R.drawable.doupnowlogo)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent);
mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
}
else
{
mBuilderOld = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
mBuilderOld.setContentTitle(title)
.setContentText(msg)
.setSmallIcon(R.drawable.doupnowlogo)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_ALL)
.setPriority(NotificationManager.IMPORTANCE_MAX);
mNotifyManager.notify(NOTIFICATION_ID, mBuilderOld.build());
}
}
But on clicking any notification by the user, he is always redirected to App's MainActivity only.
Can anyone guide me where i am missing.
If you are comparing title using api the you have to check the title using JSON object like this.
JSONObject data = json.getJSONObject("data");
String title = data.getString("title");
String message = data.getString("message");
Make sure the title you get is equal as title you are comparing and add flags in intent.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
I'm struggling to get my FCM notifications to stack in the same way as for Whatsapp:
1) The latest message for a particular room is displayed, with an updated count of all unread messages.
2) Indicating separate groupings of point 1 for notifications for different rooms.
I have spent a few hours looking at various SO questions and this is the closest I've come to finding an answer. The issue is that I am using a data payload, not notification, and it doesn't seem like the "tag" property works for my data payload.
The current behavior is that only the latest notification shows, overriding the previous.
Here is the sendNotification() method in my FirebaseMessagingService
private void sendNotification(RemoteMessage remoteMessage) {
//Intent intent = new Intent(this, StudentChatActivity.class);
String clickAction = remoteMessage.getData().get("click_action");
Intent intent = new Intent(clickAction);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
String roomID = remoteMessage.getData().get("ROOMID");
String origin = remoteMessage.getData().get("ORIGIN");
String msgID = remoteMessage.getData().get("MSGID");
Log.d(TAG, "Message data payload, roomID: " + roomID);
intent.putExtra("ROOMID", roomID);
intent.putExtra("USERID", UserID);
intent.putExtra("USERNAME", UserName);
intent.putExtra("ORIGIN", origin);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.received_message);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.small_pickle)
.setContentTitle("FCM Message")
.setContentText(remoteMessage.getData().get("body"))
.setPriority(1)
.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_HIGH);
notificationManager.createNotificationChannel(channel);
}
Log.d(TAG, "Noification ID: " + notify_no);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
So I have an app that receives the temperature via MQTT. To avoid getting spammed by notifcations, I want the app to notify once, that is vibrate, play sound and then the next three times (if the notification isn't dismissed) it will only update the temperature value. So:
Notify
Update temp
Update temp
Update temp
5(or 1 if you will) Notify
This is my code:
private final NotificationCompat.Builder builder = new NotificationCompat.Builder(this, id);
private void handleNotification(String message, String topic) {
if (notifManager == null) {
notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
if (isNotifRunning() && ticker < 3) {
updateNotif(message);
ticker++;
} else {
createNotif(message);
ticker = 0;
}
}
private void createNotif(String message) {
Intent intent;
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = notifManager.getNotificationChannel(id);
if (mChannel == null) {
mChannel = new NotificationChannel(id, name, importance);
mChannel.setDescription(description);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200});
notifManager.createNotificationChannel(mChannel);
}
intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentTitle(getString(R.string.notifTmpLowTitle))
.setSmallIcon(R.drawable.ic_ac_unit_black_24px)
.setContentText(getString(R.string.notifTmpLowText) + " " + message + Constants.CELSIUS)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setTicker(message)
.setColor(getResources().getColor(R.color.colorCold))
.setVibrate(new long[]{100, 200});
} else {
intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentTitle(getString(R.string.notifTmpLowTitle))
.setSmallIcon(R.drawable.ic_ac_unit_black_24px)
.setContentText(getString(R.string.notifTmpLowText) + " " + message + Constants.CELSIUS)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setTicker(message)
.setVibrate(new long[]{100, 200})
.setColor(getResources().getColor(R.color.colorCold))
.setPriority(Notification.PRIORITY_HIGH);
}
Notification notification = builder.build();
notifManager.notify(NOTIFY_ID, notification);
}
//TODO Doesn't update, posts a new notification.
private void updateNotif(String message) {
builder.setContentText(getString(R.string.notifTmpLowText) + " " + message + Constants.CELSIUS);
Notification notification = builder.build();
notification.flags = Notification.FLAG_ONGOING_EVENT;
notifManager.notify(NOTIFY_ID, notification);
}
//---------------------------------------------
With this code, I always get, what it looks like, a brand new notification with sound and vibration. I've looked at previous questions regarding this and they all say that it's important to use the same builder and as you can see, I have done this. Is there some change in newer Android versions that I'm not aware of? I've tested on both 7.1.1 and 8.1.
You'll want to call setOnlyAlertOnce(true) to cause updates to your notification to not send sound/vibration.