I have an application which starts a service running on the background. This service periodically issues a constant notification. I would like to be able to press that notification and resume the last activity of the application.
I am creating my notifications as follows:
public static void startNotification(Service service, String message) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(service);
if(prefs.getBoolean("pref_NotificationDisplayed", true)){
// Creates an Ongoing Notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(service.getApplicationContext()).setSmallIcon(R.drawable.ic_launcher).setContentTitle("Title").setContentText(message);
Intent toLaunch = new Intent(service.getApplicationContext(),MainActivity.class);
toLaunch.setAction("android.intent.action.MAIN");
toLaunch.addCategory("android.intent.category.LAUNCHER");
PendingIntent intentBack = PendingIntent.getActivity(service.getApplicationContext(), 0,toLaunch, PendingIntent.FLAG_UPDATE_CURRENT);
//PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(intentBack);
NotificationManager mNotificationManager = (NotificationManager) service.getSystemService(Context.NOTIFICATION_SERVICE);
// Send Notification
Notification primaryNotification = mBuilder.build();
primaryNotification.flags = Notification.FLAG_ONGOING_EVENT;
mNotificationManager.notify(10001,primaryNotification);
}
}
I have tried the solutions from here and here with no luck.
Every time I press the notification a new activity is started up rather than resuming the old activity. Is this because I am issuing the activity from a service ? or am I making an obvious error above ?
Thanks for the help.
are you try
toLaunch.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
inyour intent. check above flag i dont have tried...
Related
Im testing the push notification with my app.
when App in the foreground:
Step 1. Received the notification (in system tray).
2. now, I'm in some other screen than the home screen.
3. Actual Problem: On tap on the notification, it is going to the home screen.
4. Expected: If the app is in the foreground, just I need to cancel on tap of the notification. (No need to swipe.)
when App in background/killed: (Works well)
Step 1. Received the notification (in the system tray)
2. On tap, open the home screen of the app.
Tried with setting launch mode flags in intent. Not helped. Below is my code. Please suggest the solution guys.
Intent resultIntent = new Intent(this, MainActivity.class);
//resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
mBuilder.setContentTitle(title);
mBuilder.setContentText(body);
mBuilder.setAutoCancel(true);
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(body));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mBuilder.setChannelId(TestUtils.creatChanel(this).getId());
}
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(642, mBuilder.build());
Not sure about dismiss notification on tap, but since your concern is wrong navigation.
We can check app is in foreground or not and prevent new activity to be opened from notification click, if app is in foreground.
//If app is in foreground setting pending intent to null
PendingIntent pendingIntent;
Intent notificationIntent = new Intent(getApplicationContext(), Main2Activity.class);
if(isAppInForeground()){
Log.e("--^","inForeground");
pendingIntent = null;
}else{
Log.e("--^","inBackground");
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Add this function (SOURCE: link)
private boolean isAppInForeground() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> services = activityManager.getRunningAppProcesses();
boolean isActivityFound = false;
if (services.get(0).processName
.equalsIgnoreCase(getPackageName()) && services.get(0).importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
isActivityFound = true;
}
return isActivityFound;
}
In this case if notification came when app is in foreground, it will do nothing if clicked. So user has only one option left to swipe it to remove.
You can create Custom Notification with close button to close notification using RemoteViews
// create Notification with RemoteViews:
RemoteViews remoteViews= new RemoteViews(getApplicationContext().getPackageName(), R.layout.your_custom_notification);
Intent closeIntent = new Intent(context, CloseNotificationService.class);
hangUpIntent.setAction("close");
PendingIntent pendingCloseIntent = PendingIntent.getBroadcast(this, 0, closeNotification, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.cancel_notification, pendingCloseIntent);
// create notification here..
Notification customNotification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(remoteViews)
.build();
OnClick of close button it will redirect to service class:
public class CloseNotificationService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public CloseNotificationService() {
super("notificationIntentService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
switch (intent.getAction()) {
case "close":
Handler hangUpHandler = new Handler(Looper.getMainLooper());
hangUpHandler.post(new Runnable() {
#Override
public void run() {
NotificationManager notifManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notifManager.cancel(notificationId); // get notification id from intent.
}
});
break;
}
}
}
For more information of RemoteViews you can refer official google developer website https://developer.android.com/training/notify-user/custom-notification
Instead of this:
Intent resultIntent = new Intent(this, MainActivity.class);
do this:
Intent resultIntent = getPackageManager().getLaunchIntentForPackage("your.package.name");
and put that in your Notification. This will launch the app if it is not already running, otherwise it will just bring the app's task to the foreground in whatever state it was when the user last used it. If the user is already in the app (ie: on another screen), this will do nothing when the user clicks the Notification.
Should be exactly what you are looking for.
Inside your launcher activity have you tried notification manager class cancelAll() method??
In this way if there is already a notification on launch then it will cancelled automatically
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.
I have a background Service that triggers events and builds notifications for my app. If clicked, a notification should open the MainActivity, and depending on the info sent, open one of my Fragments within this Activity. For that, the Notification contains a PendingIntent that saves data into the Intent's Bundle.
There are three scenarios for this triggered event:
App in foreground: my service sends a Broadcast and my BroadcastReceiver in the Activity gets the event and handles it. No Notification needed. It works well.
App killed: the PendindIntent reopens my app, and my Activity accesses my info through the Bundle using getIntent().getExtras(). Everything works well.
App in background: the Activity was created already, so the BroadcastReceiver is registered. I click on my Notification, but nothing happens. Neither I receive a broadcast message, nor I can access my Bundle (checking it in onResume with getIntent().getExtras() and it's null).
Any thoughts on how to solve the third case?
Code that creates the Notification:
private void createNotification() {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.my_icon);
mBuilder.setContentTitle("My App");
mBuilder.setContentText("Notification message");
Bundle bundle = new Bundle();
bundle.putString(MainActivity.OPEN_FRAGMENT, "myFragment");
Intent resultIntent = new Intent(this, MainActivity.class);
resultIntent.putExtra("myInfo","myInfo");
resultIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
resultIntent.putExtras(bundle);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
Have you tried to change
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
to
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, 0);
Finally, I found the solution!
What happened is that on my cases:
App foreground: Service sends a Broadcast. Activity receives it and handles the event.
App killed: Notification clicked, PendingIntent launched. App reopens and handles the event with the info from Bundle.
App in background: Notification clicked, it sends a PendingIntent, however the Activity is already running so it doesn't override it, which is why nothing happened.
Solution: override the onNewIntent method:
#Override
protected void onNewIntent(Intent intent) { // Receives the PendingIntent
super.onNewIntent(intent);
if (intent.getExtras() != null && intent.getExtras().getString(OPEN_MY_FRAGMENT) != null) {
// TODO something with intent.getExtras().getString("myInfo");
}
}
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 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.