In my application I unable to recreate the activity with new information (bundle data) when tap push notification. The following is the steps of my push notification process flow.
Step 1:
I open Activity B from when click the push notification with information showing in the Activity B.
Step 2:
Tap home button or go to some other activity so Activity B goes to background (OnPause) state.
Step 3:
Now again I open Activity B via clicking push notification with new information but Activity B goes to onResume instead of onCreate state.
My requirement is it should go to onCreate state so that I can process the with the new information. How can IActivity B goes to onResume instead of onCreate state do this? I did the following in the notification receiver class.
Intent intent = new Intent(this, ListScreenActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("res_id", requestCode);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("uid", id_value);
intent.putExtras(bundle);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, requestCode, intent,0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext());
Notification notification = mBuilder
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker(tickerMessage)
.setWhen(0)
.setAutoCancel(true)
.setContentTitle(app_name)
.setStyle(new NotificationCompat.BigTextStyle().bigText(tickerMessage)
.setContentIntent(resultPendingIntent)
.setContentText(tickerContent).build();
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) System.currentTimeMillis(), notification);
Note:
here ListScreenActivity (Activity B) is not Launcher activity
You can't change the Android activity lifecycle. You should expect this same thing can happen every time. onCreate is only called once per instance of an activity object. That can't be changed. You can read about the activity lifecycle to get more information.
If you want to close existing activity stack regardless of what's in there and create new root, correct set of flags is the following:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Related
I have created a custom notification, but when i pause the activity with the home button and a notification arrives, i press the notification and it creates a new activity and doesnt resume the previews activity and when i press the back button it goes to the previews one which is the same window. I have tried singleTop, singleTask, singleIntent, it works but it doesnt update the activity when a message enters, it is like the previews activity was in pause. how can i fix it?
if there is no solution i though in resuming the activity or destroy the paused activity or maybe restart the activity, is there a way to do this?
public void CustomNotification(String strtext) {
// Using RemoteViews to bind custom layouts into Notification
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.customnotification);
// Set Notification Title
String strtitle = getString(R.string.customnotificationtitle);
// Open NotificationView Class on Notification Click
Intent intent = new Intent(this, NotificationView.class);
// Send data to NotificationView Class
intent.putExtra("title", strtitle);
intent.putExtra("text", strtext);
intent.putExtra("String T", "");
//intent.putExtra("Integer C", 0);
// Open NotificationView.java Activity
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
// Set Icon
.setSmallIcon(R.drawable.ic_launcher)
// Set Ticker Message
.setTicker(getString(R.string.customnotificationticker))
// Dismiss Notification
.setAutoCancel(true)
// Set PendingIntent into Notification
.setContentIntent(pIntent)
// Set RemoteViews into Notification
.setContent(remoteViews);
// Locate and set the Image into customnotificationtext.xml ImageViews
remoteViews.setImageViewResource(R.id.imagenotileft,R.drawable.ic_launcher);
remoteViews.setImageViewResource(R.id.imagenotiright,R.mipmap.ic_action_chat);
// Locate and set the Text into customnotificationtext.xml TextViews
remoteViews.setTextViewText(R.id.title,getString(R.string.customnotificationtitle));
remoteViews.setTextViewText(R.id.text, strtext);
// Create Notification Manager
NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Build Notification with Notification Manager
notificationmanager.notify(0, builder.build());
}
LOGS:
04-29 01:29:10.453 29001-29001/com.example.example E/STATE﹕NEW ACTIVITY
04-29 01:29:15.376 29501-29501/com.example.example D/Activity﹕ Activity.onPause(), editTextTapSensorList size: 0
04-29 01:30:06.981 29501-29501/com.example.example E/STATE﹕ RESUMING
WHEN I PRESS THE NOTIFICATION:
04-29 01:33:09.654 33449-33530/com.example.example E/STATE﹕NEW ACTIVITY
I will appreciate any answer, Thanks!
EDITED
ANSWER:
the answer was to add:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
because when i was in the same window and i pressed the home button, the activity was in paused, then if some notification arrived it brought me to that window but didnt updated the messages so I needed to create a new intent and erase the previous one which was in pause. so that code did the Job.
To update your activity, you should override onNewIntent():
protected void onNewIntent (Intent intent) {
super.onNewIntent(intent);
//reload your data here
}
Android Docs say:
void onNewIntent (Intent intent)
This is called for activities that set launchMode to "singleTop" in
their package, or if a client used the FLAG_ACTIVITY_SINGLE_TOP flag
when calling startActivity(Intent). In either case, when the activity
is re-launched while at the top of the activity stack instead of a new
instance of the activity being started, onNewIntent() will be called
on the existing instance with the Intent that was used to re-launch
it.
An activity will always be paused before receiving a new intent, so
you can count on onResume() being called after this method.
Note that getIntent() still returns the original Intent. You can use
setIntent(Intent) to update it to this new Intent.
Note: as the docs say, you need to set android:launchMode="singleTop" in your Activity tag (in AndroidManifest).
try this in your service code to use notification :
private static final int NOTIFY_ME_ID = 1222;
NotificationManager mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
private void Notifi(String message){
int requestID = (int) System.currentTimeMillis();
Intent intent = new Intent(Intent.ACTION_MAIN);
//CLEAR PREVIOUS ACTIVITIES AND CREATE A NEW ONE
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setComponent(new ComponentName("packagenameofyourapplication",
"packagenameofyourapplication.NotificationView"));
PendingIntent pintent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification notif = new Notification.Builder(this)
.setContentTitle(getString(R.string.notification_titel)).setContentText(message)
.setSmallIcon(R.drawable.ic_launcher).setAutoCancel(true)
.setContentIntent(pintent).build();
notif.flags = Notification.FLAG_NO_CLEAR;
mNotificationManager.notify(NOTIFY_ME_ID, notif);
}
I am creating notifications with following code:
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setContentTitle(messageBody)
.setAutoCancel(true)
.setSmallIcon(R.drawable.top_icon)
.setContentText(senderName)
.setTicker(senderName+" ")
.setSound(soundUri);
Intent resultIntent = new Intent(this, LoginActivity.class);
resultIntent.putExtra("gcm_username",senderName);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_ONE_SHOT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(NotificationID.getID(senderName), mBuilder.build());
When user clicks the notification I am catching it with following code in loginActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
gcmUserId= getIntent().getStringExtra("gcm_username");
startAction(gcmUserId);
....
My problem starts here.
Scenario:
1)When app is closed user receives notifications from 2 different users
2)User clicks first notification and app starts then startAction method calls.
3)Then user clicks the second notification
But when user clicks the second notification app has already started so startAction won't be able to call again because it is in the onCreate method.How can catch second notification ?
You can handle it inside onNewIntent(). You would need to override that method inside your activity. The docs say:
This is called for activities that set launchMode to "singleTop" in their package, or if a client used the FLAG_ACTIVITY_SINGLE_TOP flag when calling startActivity(Intent). In either case, when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
So what I have is a notification in my status bar which when clicked by the user brings up an activity with no title, to replicate a dialog. But I have a problem. If I open up the app, then just click the home button, and then click the notification in my status bar. It brings up apps main activity with the notificatoins activity stacked on the top. What I want to do is make it so when I click the notification it clears all the bottom activities so that never happens. Here's the code I use to start the notification activity
// Send Notification
Intent intent1 = new Intent(this, Dialog.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent1, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_quick_tweet_icon)
.setContentTitle("Dialog")
.setContentText("Touch for more options")
.setWhen(System.currentTimeMillis())
.setContentIntent(pIntent)
.setAutoCancel(false).setOngoing(true);
NotificationManager nm = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notif = builder.getNotification();
nm.notify(1, notif);
This isn't going to work. You've written:
Intent intent1 = new Intent(this, Dialog.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
What this says is "if activity Dialog already exists in the task stack, clear (finish) all activities that are on top of that in the stack before starting the Dialog activity. Otherwise (if there is no instance of Dialog already in the stack) just start the Dialog activity". So what you are seeing is that your Dialog activity is put on top of the other activities that are already in the task stack.
If you want this notification to remove all activities from the task stack and then start your Dialog activity, I suggest you do the following:
Create the notification like this:
Intent intent1 = new Intent(this, MyRootActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent1.putExtra("startDialog", true);
in this case, MyRootActivity must be the root activity of the task (ie: the one that has ACTION=MAIN and CATEGORY=LAUNCHER in the manifest).
In onCreate() of MyRootActivity do this:
super.onCreate(...);
if (getIntent().hasExtra("startDialog")) {
// User has selected the notification, so we show the Dialog activity
Intent intent = new Intent(this, Dialog.class);
startActivity(intent);
finish(); // finish this activity
return; // Return here so we don't execute the rest of onCreate()
}
... here is the rest of your onCreate() method...
Hopefully this is clear.
I got some issue regarding about the notification intent. I have 2 activity (A & B). Activity A is the main activity of my application. The first activity that user will go through. As for activity B is when the user enter by clicking on a button at Activity A.
The thing is when I clicked on my notification and it will direct me to Activity B. Then direct me back to Activity A onBackPressed. But when I close the application and open it back through the multi-tasking option, it resume my application at Activity B. I wanted the application to start back at Activity A instead after closing it.
The order should be
Activity A --> Activity B.
Notification onClick -> Activity B (onBackPressed) -> Activity A --> Close.
Re-open the app / open with multi-tasking feature --> Activity A
Please do let me know if there is any other information that I can provide for a proper understanding to my question.
GCM_Intent.class
Notification note = new Notification(icon, msgTopic ,System.currentTimeMillis());
Intent i=new Intent(this, Activity_B.class);
i.putExtra("topicId", topicId);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi=PendingIntent.getActivity(this, CommunitiesappConstant.NOTIFICATION_ID, i, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
note.setLatestEventInfo(this, topicName ,msgInfo+message, pi);
note.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
note.ledARGB |= 0xff0000ff;
note.ledOffMS |= 1000;
note.ledOnMS |= 300;
mgr.notify(CommunitiesappConstant.NOTIFICATION_ID, note);
Activity B.class
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
Bundle bundle = getIntent().getExtras();
topicId = bundle.getString("topicId");
}
#Override
public void onBackPressed() {
super.onBackPressed();
Log.e(TAG, "onBackPressed");
Intent i = new Intent(Activity_B.this, Activity_A.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
Notification is a message you can display to the user outside of your application's normal UI.This is perfect code to use of notification.
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("My notification")
.setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
I am using an Activitiy with various Tabs on it. From a different part of the application, Notifications are created to tell the user that something has changed. I now managed to Call the Activity, when the user clicks on the Notification. But how can i determine wheter a Activity is created the "normal" way during runtime or by clicking on the notification?
(Depending on the notification clicked, i want to forward to another tab instead of showing the main Tab.)
Intent intent = new Intent(ctx, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, intent, 0);
// TODO: Replace with .Build() for api >= 16
Notification noti = new Notification.Builder(ctx)
.setContentTitle("Notification"
.setContentText(this.getName())
.setSmallIcon(R.drawable.icon)
.setContentIntent(pendingIntent)
.setDefaults(
Notification.DEFAULT_SOUND
| Notification.DEFAULT_LIGHTS)
.setAutoCancel(true)
.getNotification();
NotificationManager notificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
// Hide the notification after its selected
notificationManager.notify(this.getId(), noti);
This successfully calls my MainActivity. But is there some Method that is called when the Activity is triggered by the pendingIntent?
Thought about to define something like this in the Main Activity:
onTriggeredByNotification(Notification noti){
//determinte tab, depending on Notification.
}
Pass a boolean value from notification and check for the same in the onCreate method of the activity.
Intent intent = new Intent(ctx, MainActivity.class);
intent.putExtra("fromNotification", true);
...
if (getIntent().getExtras() != null) {
Bundle b = getIntent().getExtras();
boolean cameFromNotification = b.getBoolean("fromNotification");
}
You can try this in your Notification
Intent intent=new Intent();
intent.setAction("Activity1");
In the Activity override onNewIntent() method and get action so you can determine the activity is called or not.
Better than using the reserved action field of your intent as specified by #ricintech, you could use an extra parameter in your pending intent and detect it in your onCreate method and in your onNewIntent metod inside your activity.