I have a notification in my app and I want it to bring back an existing activity when the user clicks it.
The notification is genereated within the activity I want to bring back so I assume it still exists.
This is my code for the notification:
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification noti = new Notification(R.drawable.icon, "s", 0);
CharSequence title = "S";
CharSequence details = "W";
Intent intent = new Intent(getBaseContext(), Start.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
PendingIntent pending = PendingIntent.getActivity(getBaseContext(), 0, intent, 0);
noti.setLatestEventInfo(Start.this, title, details, pending);
nm.notify(0,noti);
But for some reason it keeps creating a new activity.
what am I doing wrong?
"The notification is genereated within the activity I want to bring back so I assume it still exists." Well, it may, but it's not generally a good idea for you to count on that. What if the user clicks on the notification only after backing out of your app using the back button, or after some length of time during which the OS has killed your activity while the user has been doing other things? Is there a particular reason why you need the "old" activity? If it has a state that you need to preserve or recreate, you can do that: have a look at http://developer.android.com/training/basics/activity-lifecycle/recreating.html and http://developer.android.com/guide/components/activities.html#SavingActivityState.
Related
I am able to generate and display multiple notifications, all starting the same activity but displaying different information depending on the extra that is attached to the intent that starts up the Activity. When I am within my application, all the notifications are able to start the Activity, but when I am outside of the application, only one is able to start the Activity (the first that I click on), the rest do nothing once clicked on (except disappear). This is my code for generating the notifications. The "reqCode" represents unique numbers.
Resources r = getResources();
Intent i = new Intent(this, DisplaySearchTickerAlert_Activity.class);
i.putExtra(NewArticleNotification_Service.QUERY_TICKER, searchQuery);
PendingIntent pi = PendingIntent.getActivity(this, reqCode, i, 0);
Notification notification = new NotificationCompat.Builder(this)
.setTicker(r.getString(R.string.ticker_alert))
.setSmallIcon(android.R.drawable.ic_menu_call)
.setContentTitle(r.getString(R.string.ticker_alert))
.setContentText("Newly published for search term: " + "\""
+ searchQuery + "\"").setContentIntent(pi).setAutoCancel(true).build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(reqCode, notification);
That is because your activity is already being displayed. Only the first notification will bring it to the foreground. The rest of notifications will dispatch a new intent that depending on your activity android:launchMode you might be able to catch on the onNewIntent callback.
My question is a bit complicated so I am going to describe it briefly what I want to achieve. My application receives messages from GCM without any issue. When application is running and is visible to the user I am not displaying notification in Action Bar, I am displaying this message in dialog alert. I use BroadcastReceiver to achieve this.
The main issue is that, when app gets a few notifications in no time. When main activity is visible to the user, the first notification will be shown in dialog alert. And next will be placed in Action Bar as usual Android notifications. And at this moment user disposes the dialog alert and is going to choose a next notification from Action Bar. At this moment I am using in my CloudService (extends IntentService) intent with flag Intent.FLAG_ACTIVITY_CLEAR_TOP and also PendingIntent.FLAG_UPDATE_CURRENT flag for pendingIntent. PendingIntent is just the contentIntent for my NotificationCompat.Builder.
It works in this way that for each user click on the notification from Action Bar, my activity is refreshing (floats to the lower device edge and then floats from the upper edge with dialog alert with message - I am getting the extras from the intent in onResume method). This action is quite OK. Activity has only one instance in that case - I don't have to break through the few instances of the same activity while I have opened few notifications. But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.
There are two methods in CloudService which handle cloud messages:
private void showNotification(Bundle extras) {
notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
String message = extras.getString(CloudMetaData.MESSAGE);
if (App.isMyActivityVisible() && !CloudMessageDialogFragment.isAttached()) {
sendBroadcast(message, NOTIFICATION_ID);
} else {
Intent intent = new Intent(this, MyParentActivity.class);
intent.putExtra(CloudMetaData.MESSAGE, message);
intent.putExtra(CloudMetaData.NOTIFICATION_ID, NOTIFICATION_ID);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle(getString(R.string.app_name));
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(alert));
builder.setContentText(alert);
builder.setAutoCancel(true);
builder.setDefaults(Notification.DEFAULT_SOUND);
builder.setContentIntent(contentIntent);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
NOTIFICATION_ID++;
}
And method which send broadcast is just like that:
private void sendBroadcast(String message, int notificationId) {
Intent intent = new Intent();
intent.setAction(ACTION_FROM_CLOUD_SERVICE);
intent.putExtra(CloudMetaData.MESSAGE, message);
intent.putExtra(CloudMetaData.NOTIFICATION_ID, notificationId);
sendBroadcast(intent);
}
In which way can I achieve similar solution? But it is important for user of course to open notification from Action Bar and shown him its correct message.
EDIT
I have switched my dialog alert into the dialog activity. This is its definition in AndroidManifest:
<activity
android:name="com.myapp.activity.CloudMessageDialogActivity"
android:theme="#android:style/Theme.Dialog"
android:parentActivityName="com.myapp.activity.MyParentActivity"/>
But the result is still the same - when app receives a few notifications, clicking on one of them will open the dialog with the intent for the last received notification.
But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.
That's because you are using the same request code (i.e., 0) for all PendingIntents here:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
By doing so, you are ultimately receiving the same intent, because the platform is failing to see the difference between the intents and delivering the same object everytime:
... it is important to know when two Intents are considered to be the same for purposes of retrieving a PendingIntent. A common mistake people make is to create multiple PendingIntent objects with Intents that only vary in their "extra" contents, expecting to get a different PendingIntent each time. This does not happen. The parts of the Intent that are used for matching are the same ones defined by Intent.filterEquals. If you use two Intent objects that are equivalent as per Intent.filterEquals, then you will get the same PendingIntent for both of them.
So, instead of a constant value, please use a unique request code. For e.g. change the above line with:
PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Hope this helps.
I'm a bit confused with pending intents in the notification builder. I've got a MainActivity activity and a MessageList activity. I have a service to show a notification when a new message in found, and I want it to be that if the user presses the notification it opens to the MessageList activity but when they press back they will return to the activity they were in.
Essentially I want to add MessageList activity to the top of the activity stack when they press the notification without modifying the current activity stack.
Thank you
Okay, so I got it to work with some old code I wrote a while back. This does what I wanted -
Intent notificationIntent = new Intent(this, AlertListActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
mBuilder.setContentIntent(contentIntent);
I have a method which receives text from a push notification, via the Parse API, and packages it into a notification object. Pretty standard stuff. My problem is that I'm trying to use a BigTextStyle to display my notification in the list, but it refuses to do so, and only shows one line of text and the two-finger gesture does not cause it to expand.
However, if I tap the notification, which opens the app, then return to the notification list, it is displayed in the BigTextStyle and is responsive to gestures. So, my guess is that somehow tapping on the notification is activating it and allowing the BigTextStyle code to kick in.
I like that tapping on the notification opens the app, but I don't want to force my users to open the app then close it again to see the full text of my messages. So is there a way I could either make the notification display in the BigTextStyle format from the start, or to make it so that the first click "activates" the notification, allowing the full message text to be seen, and then a second click opens the app? Any help would be appreciated.
Here is my code from the Notification method:
public void receiveNotification() {
NotificationCompat.BigTextStyle bts = new NotificationCompat.BigTextStyle();
bts.bigText(SplashActivity.globalDataString);
bts.setSummaryText("Tap to open app, swipe to dismiss message");
NotificationCompat.Builder m = new NotificationCompat.Builder(this);
m.setContentTitle("New Push Notification")
.setContentText(SplashActivity.globalDataString)
.setSmallIcon(R.drawable.app_icon)
.setStyle(bts)
.build();
Intent openApp = new Intent(this, MenuActivity.class);
// This ensures that navigating backward from the Activity leads out of
// the application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MenuActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(openApp);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
m.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(pushMessageID, m.build());
pushMessageID++;
//reset notification
flag1 = false;
}
EDIT: I think my problem is with where I'm calling my receiveNotification() method from. Right now I have it in the onCreate() method of my app's starting activity, which doesn't make much sense looking back. Should I put it in my broadcastReceiver class, or would there be a better place to put it?
Yes, the creation and display of the notification is usually done either in the broadcast receiver, or in an intent service started by the broadcast receiver. Only when the user taps the notification, the relevant activity is launched. You can see Google's client code sample here.
I'm trying to get my home screen widget to trigger the config class for a new widget but am having a problem.
When a user tries to add my widget to the home screen for the first time it kicks off a thread which downloads a file with a list of sensors and then exits. Once the download is complete the download task triggers a notification. When the user taps on the notification it should start the dataWidgetConfig activity. This works, to a point using this code
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
final Notification notifyDetails = new Notification(R.drawable.icon,"Sensor list downloaded.",System.currentTimeMillis());
CharSequence contentTitle = "Notification Details...";
CharSequence contentText = "Sensor list has downloaded, tap to add widget.";
Intent notifyIntent = new Intent(self, dataWidgetConfig.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notifyIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getActivity(self, appWidgetId, notifyIntent, 0);
notifyDetails.setLatestEventInfo(self, contentTitle, contentText, pendingIntent);
mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
My problem is, that I don't have an appWidgetId. When I add a widget via long press on the home screen I get allocated an appWidgetId, how do I ask the home screen for one? I'm guessing I can't just make one up since it might either be in use already or get allocated later.
At the moment my activity launches ok, but exits because I've deliberately set my appWidgetId as:
AppWidgetManager.INVALID_APPWIDGET_ID;
Can anyone give me any ideas on this?