I have implemented smooch. https://smooch.io/
And my issue is that when I get the notification from smooch. If I'm in the background, I set a "unread messages" long that I use in my main activity on the smooch button.
The issue is that when I press on the notification, and the ConversationActivity is started from there. I need to set the unread messages to 0, because the ConversationActivity is opened. How can I know when this happens?
I cannot modify ConversationActivity.class from the smooch library.
I thought about making the notification myself, and changing the smooch created one with this one using this code:
private static void generateNotificationSmooch(final Context context, String title, String message) {
if (title == null)
title = context.getString(R.string.passenger_name);
Intent notificationIntent = new Intent(context, ConversationActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);
PendingIntent intent = PendingIntent.getActivity(context, iUniqueId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
mBuilder.setContentTitle(title).setContentText(message).setSmallIcon(R.drawable.notification_icon);
mBuilder.setContentIntent(intent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
}
But I need to set the unread to 0 when the notification is pressed, and not when I create the notification. And I can't put it in pending intent
You have a few options.
Use the onSmoochShown delegate callback.
This callback will be triggered when the conversation is shown, so you will be able to update your unread count.
Use the onUnreadCountChanged delegate callback
.
This delegate will be called whenever the unread count changes for current user. You can use this callback to update your long accordingly.
Since you will need to be listening to these delegate callbacks when a notification is tapped, it may be best to set your delegate in your Application’s onCreate, after you initialize Smooch.
Related
Notification setAutoCancel(true) doesn't work if clicking on Action
I have a notification with an action within it. When I tap on the notification it gets removed from the list. However, when I click on the Action it successfully completes the Action (namely makes a call), but when I return to the list of notifications, it remains there.
Relative code of the AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
Meeting meeting;
/**
* Handle received notifications about meetings that are going to start
*/
#Override
public void onReceive(Context context, Intent intent) {
// Get extras from the notification intent
Bundle extras = intent.getExtras();
this.meeting = extras.getParcelable("MeetingParcel");
// build notification pending intent to go to the details page when click on the body of the notification
Intent notificationIntent = new Intent(context, MeetingDetails.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.putExtra("MeetingParcel", meeting); // send meeting that we received to the MeetingDetails class
notificationIntent.putExtra("notificationIntent", true); // flag to know where the details screen is opening from
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
// build intents for the call now button
Intent phoneCall = Call._callIntent(meeting);
if (phoneCall != null) {
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, 0, phoneCall, PendingIntent.FLAG_CANCEL_CURRENT);
int flags = Notification.FLAG_AUTO_CANCEL;
// build notification object
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder.setContentTitle("Call In")
.setContentText(intent.getStringExtra("contextText"))
.setTicker("Call In Notification")
.setColor(ContextCompat.getColor(context, R.color.colorBluePrimary))
.setAutoCancel(true) // will remove notification from the status bar once is clicked
.setDefaults(Notification.DEFAULT_ALL) // Default vibration, default sound, default LED: requires VIBRATE permission
.setSmallIcon(R.drawable.icon_notifications)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(meeting.description))
.addAction(R.drawable.icon_device, "Call Now", phoneCallIntent)
.setCategory(Notification.CATEGORY_EVENT) // handle notification as a calendar event
.setPriority(Notification.PRIORITY_HIGH) // this will show the notification floating. Priority is high because it is a time sensitive notification
.setContentIntent(pIntent).build();
notification.flags = flags;
// tell the notification manager to notify the user with our custom notification
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
}
}
}
use this flag:
Notification.FLAG_AUTO_CANCEL
inside this:
int flags = Notification.FLAG_AUTO_CANCEL;
Notification notification = builder.build();
notification.flags = flags;
Documentation
Ok turns out it's a known problem already, and it needs extra code to be done (keeping reference to notification through id). Have no clue why API does not provide this, as it seems very logical to do. But anyways,
see this answer in stackoverflow:
When you called notify on the notification manager you gave it an id - that is the unique id you can use to access it later (this is from the notification manager:
notify(int id, Notification notification)
To cancel, you would call:
cancel(int id)
with the same id. So, basically, you need to keep track of the id or possibly put the id into a Bundle you add to the Intent inside the PendingIntent?
I faced this problem today, and found that FLAG_AUTO_CANCEL and setAutoCanel(true), both work when click on notification,
but not work for action click
so simply, in the target service or activity of action, cancel the notification
NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancelAll();
or if have more notification
manager.cancel(notificationId);
You have created two pending intent use in boths and change Flag too.
PendingIntent pIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), notificationIntent, 0);
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), phoneCall, PendingIntent.FLAG_UPDATE_CURRENT);
// CHANGE TO THIS LINE
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, 0, phoneCall, PendingIntent.FLAG_CANCEL_CURRENT);
I have a service that shows a notification PendingIntent each time it receives a new GCM message. The problem is that the GCM messages can be of different kinds. And if many notifications leave unread, I want not to show them separately but in groups like:
you have 3 unread messages of type A
you have 2 unread messages of type B
you have 4 unread messages of type C
As far as I understand, to get this effect I need to have an access to unread/unseen notifications. Each time when I new notification comes I can check, if there is another unread message of this type, and then decide, whether I create a new notification or update an old one.
My question is: is there a way to see, which notifications are unseen and get access to them?
For any case this is my method to create a message; if an argument notificationId is 0 a new notification should be created. Else - updated.
private int sendNotification(String msg, Integer notificationId) {
Log.d(TAG, "sending message with text: "+msg);
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Random random = new Random();
int notification_id = notificationId==0?random.nextInt(9999 - 1000) + 1000:notificationId;
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.notification);
Intent intent = new Intent(this, MainActivity.class);
// Send data to NotificationView Class
intent.putExtra("text", msg);
PendingIntent pending= PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("escos")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(pending);
mBuilder.setContent(remoteViews);
remoteViews.setTextViewText(R.id.notiftext, msg);
remoteViews.setImageViewResource(R.id.notifim, R.drawable.ic_launcher);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mNotificationManager.notify(notification_id, notification);
return notification_id;
}
For different Notification strip (A, B, C etc.) in your status bar, use different NOTIFICATION_ID for building the Notification on basis of your defined type or collapse_key received from GCM.
For determining unread and read messages, use a local variable (counter) in Shared Preferences and increment it each time a specific type of Notification comes (on basis of defined type or collapse_key).
Then generate the Notification with that particular NOTIFICATION_ID as Notification with particular NOTIFICATION_ID can override each other. So You can override the previous Notification with Iterative Numbered text in New Notification.
As soon as user click on any Notification or particular Notification, clear the notification and reset the value of (counter) in Shared Preferences.
Edit1 : When you click on Notification with particular Pending Intent, then in that Activity use this code for removing all the Notifications generated from your app :
NotificationManager nMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
try {
nMgr.cancelAll();
} catch (Exception e) {
e.printStackTrace();
}
Note : Do remember to add Try-Catch before you call cancelAll() as cancelAll() may not be supported by the device model and will generate
java.lang.SecurityException: Permission Denial
error.
Edit 2:
You can also use nMgr.cancel(NOTIFICATION_ID); to clear a specific notification, pass NOTIFICATION_ID to particular intent via extras and get the extras in that activity to cancel a particular notification.
And as you click on any notification it will be cleared from status bar unless you have not set .setAutoCancel(false) in your Notification Builder.
Is it possible not launch new activity if we receive a push notification while the app is running?
My activity works with fragments and I want to do transition to a determinate fragment when the notification is received. My activity have data that I need to show the fragments. The problem is that when I receive the push notification while the app is running the method onDestroy is called and here I clear the data and then the app crash because the data are null. How can I do to not create new activity when the app receive a push notification while is running? In case the app is running I want that if you click the notification do a transition fragment, not create again the activity.
Thanks in advance.
First of all, I think that you mean "notification" to be a "message", but not android.app.Notification class.
And second, I don't think it's a best practise to raise new GUI when receiving a message, which would interrupt the user interaction. For details, please refer to: http://developer.android.com/training/notify-user/index.html and http://developer.android.com/design/patterns/notifications.html.
At last, if you really wanna do what you stated in your thread, I wonder why the data used to generate the show-data fragment is held in the activity. Try holding the data in an android.app.IntentService object, and then generate transfer the data to new activity, and then use android.app.Fragment.setArguments method to transfer the data from activity to fragment.
I think that this code will help you. This which you need is PendingIntent, it make transaction to desired activity.
/**
* Issues a notification to inform the user that server has sent a message.
*/
private static void generateNotification(Context context, String title,
String message) {
//get the default notification sound URI
Uri uriNotificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//make intent to the application. if the application is opened just maximize it.
Intent homeIntent = new Intent(context, 'your desired activity');
homeIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
homeIntent, 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("eCommCongress")
.setContentText(message)
.setLights(Color.GREEN, 1500, 1500)
.setSound(uriNotificationSound)
.setAutoCancel(true)
.setContentIntent(contentIntent);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(counter, mBuilder.build());
counter++;
}
It is perfectly possible and I do such a thing in one of my apps. First, you need to declare your activity as android:launchMode="singleTop",
Then, when you build you must configure your pending intent not to fire a new instance of your activity:
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent("YOUR ACTION HERE");
intent.setClassName(this, MainActivity.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent resultPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.defaults |= Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS;
notification.flags |= Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(idNotificacion,notification);
Now all you have to do is to override your onNewIntent inside your Activity and do whatever you want with your fragment:
#Override
protected void onNewIntent(Intent intent) {
MiLog.i(getApplicationContext(),"IntentShit","new intent received");
MiLog.i(getApplicationContext(),"IntentShit","Action: "+intent.getAction());
if(intent.getAction()!=null && intent.getAction().equals("YOUR ACTION HERE"){
//DO your stuff here
}
}
You should also take a look at this page for more info:
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
I am creating a notification from a service; the notification is shown, but when I click on it, nothing happens: It was supposed to open an activity.
My code:
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, "test", when);
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent intent = PendingIntent.getActivity(this, 0,
notificationIntent,PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, "title", "message", intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
However if I use pretty much the same code from inside an activity, I can click on the notification, and my activity is shown. What am I doing wrong?
EDIT:
It turns out that there was nothing wrong with this code, there was a different issue:
When my service finished, it created the notification with the code above. However, the service also broadcasted that it was finished, and the receiver created another notification, which used a different code to create the notification (with no PendingIntents, so no defined action when the notification is clicked), and that notification must have placed itself instead of the original, correct one.
On top of using Notification.Builder for above Android 3.0, or NotificationCompat.Builder in support library v4 as #Raghunandan suggests in the comment, I had the same problem with a possible common solution to your problem.
This is specific to 4.4 as seen here:Issue 63236:Notification with TaskStackBuilder.getPendingIntent() is not open the Activity and here Issue 61850: KitKat notification action Pending Intent fails after application re-install
One confirmed solution is to perform cancel() operation on an identical PendingIntent with the one you are about to create.
What worked for me was to modify the target Activity's manifest definition and add
android:exported="true" within "activity" tags for the target Activity. That would be MainActivity in your case I assume.
Example:
<activity
android:name="com.your.MainActivity"
android:exported="true" >
.
.
</activity>
This works with api level 8.
private int NOTIFICATION_ID = 1;
private Notification mNotification;
private NotificationManager mNotificationManager;
private PendingIntent mContentIntent;
private CharSequence mContentTitle;
you can create notification like this :
mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
//create the notification
int icon = R.drawable.ic_launcher;
CharSequence tickerText = mContext.getString(R.string.noti_comes); //Initial text that appears in the status bar
long when = System.currentTimeMillis();
mNotification = new Notification(icon, tickerText, when);
//create the content which is shown in the notification pulldown
mContentTitle = mContext.getString(R.string.noti_comes_t); //Full title of the notification in the pull down
CharSequence contentText = clck_see_noti; //Text of the notification in the pull down
//you can set your click event to go to activity
mContentIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, MainActivity.class), 0);
//add the additional content and intent to the notification
mNotification.setLatestEventInfo(mContext, mContentTitle, contentText, mContentIntent);
//make this notification appear in the 'Ongoing events' section
mNotification.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL ;
//show the notification
mNotificationManager.notify(NOTIFICATION_ID, mNotification);
and do not forget the your service is registering in the manifest
<service
android:name="com.xx.your_service"
android:enabled="true"
>
</service>
If you define an Activity that is not registered into the AndroidManifest.xml the notification will not show any error message, and nothin happen.
Intent notificationIntent = new Intent(this, MainActivity.class);
be sure to have the Activity to start from the notification registered into the AndroidManifest.xml
This guy had a similar problem "I misspelled my activity name in the manifest.":
launch activity from service when notification is clicked
Im my case my project use Android Annotations. So my error was when I created the Intent, I always set this:
Intent notificationIntent = new Intent(this, MainActivity.class);
But is necessary to set the Android Annotation's generated class:
Intent notificationIntent = new Intent(this, MainActivity_.class);
That's solves my problem
I try to make my notification(from Service) updating or refreshing in every five minutes. How can I do this? This is, what i want to update.
if (...){
int icon = R.drawable.updatedImage1;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence message = "II Tydzień";
Notification notification = new Notification(icon, message, when );
String title = this.getString(R.string.app_name); // Here you can pass the value of your TextView
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP );
PendingIntent intent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, title, message, intent);
notification.flags |= Notification.FLAG_NO_CLEAR;
notificationManager.notify(0, notification);
} else { ...other notification }
Condition is period of time, so I need to change notification depending on what time is it.
You can use AlarmManager to schedule your notification repeatedly at different time intervals. The docs mention that:
This class provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running
You might be able to use setRepeating function for your purpose.