I think I've just found a really strange bug... But it can just be somekind of feature that I never heard of.
On my application if I have any Activity on the AndroidManifest with android:launchMode="singleInstance" when you try to "clean" the stack to a certain point with the following code:
Intent intent = new Intent(this, Xpto.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
It goes to that activity. But when you press back, it returns to the previous.that should have been finished...
Example:
A -> B -> C
Then from C I call A with Intent.FLAG_ACTIVITY_SINGLE_TOP| Intent.FLAG_ACTIVITY_CLEAR_TOP having A singleInstance on the Manifest. It goes to A but it only brings it to front. And does not finishes C and B.
Can somebody explain this behaviour?
The Xpto class I'm calling is at the time the root activity of the stack.
from reading this thread:
http://groups.google.com/group/android-developers/browse_thread/thread/5eb400434e2c35f4
it seems that:
"The currently running instance of activity B in the above example will
either receive the new intent you are starting here in its onNewIntent()
method, or be itself finished and restarted with the new intent. If it
has declared its launch mode to be "multiple" (the default) and you have
not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be
finished and re-created; for all other launch modes or if
FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to
the current instance's onNewIntent(). "
which means that you need to set your launchMode to multiple instance, and use only FLAG_ACTIVITY_CLEAR_TOP.
Intent intent = new Intent(this, Xpto.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
In the scenario you described, activity's B and C are not finished when you start activity A (which is the root activity). The documentation describes that with launch mode of singleInstance and the flag FLAG_ACTIVITY_SINGLE_TOP set, activities B and C will NOT be finished. If you want to have activities B and C finished, then you must set the launch mode to multiple instance and NOT set the flag FLAG_ACTIVITY_SINGLE_TOP.
Related
This question already has answers here:
Finish all previous activities
(28 answers)
Closed 7 years ago.
This is the scenario
Activity A -> Activity B -> Activity C -> Activity D (I would like to destroy Activity A, B, and C after Activity D is launched.
Any ideas please?
Intent intent = new Intent(ActivityC.this, ActivityD.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
FLAG_ACTIVITY_NEW_TASK
If set, this activity will become the start of a new task on this
history stack. A task (from the activity that started it to the next
task activity) defines an atomic group of activities that the user can
move to. Tasks can be moved to the foreground and background; all of
the activities inside of a particular task always remain in the same
order. See Tasks and Back Stack for more information about tasks.
This flag is generally used by activities that want to present a
"launcher" style behavior: they give the user a list of separate
things that can be done, which otherwise run completely independently
of the activity launching them.
When using this flag, if a task is already running for the activity
you are now starting, then a new activity will not be started;
instead, the current task will simply be brought to the front of the
screen with the state it was last in. See FLAG_ACTIVITY_MULTIPLE_TASK
for a flag to disable this behavior.
This flag can not be used when the caller is requesting a result from
the activity being launched.
FLAG_ACTIVITY_CLEAR_TASK
If set in an Intent passed to Context.startActivity(), this flag will
cause any existing task that would be associated with the activity to
be cleared before the activity is started. That is, the activity
becomes the new root of an otherwise empty task, and any old
activities are finished. This can only be used in conjunction with
FLAG_ACTIVITY_NEW_TASK.
You need to pass flag Intent.FLAG_ACTIVITY_CLEAR_TOP with Intent :
Intent intent = new Intent(getApplicationContext(), D.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Use these lines to clear the activity stack when the Activity C is launched:
Intent i = new Intent(PresentActivityName.this, D.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
I have 3 activity . Activity A ,Activity B, Activity C.
This is the flow A->B->C.
Now i want to come to activity A from C .(i.e C->A) without getting its onCreate() called of Activity A.
so far my code is:But it will call onCreate() of ActivityA.
I want to call Restart().
Intent intent=new Intent(ActivityC.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
Two cases:
If you want to keep other activities live and just want to bring A to front, just use intent flag FLAG_ACTIVITY_REORDER_TO_FRONT.
If you don't want to clear all activities and want existing instance of A at top, then use intent flags FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP.
Note : If you use only FLAG_ACTIVITY_CLEAR_TOP, then onCreate will be called.
Keep android:launchMode="singleTask" in manifest at activity declaretion
An Activity with singleTask launchMode is allowed to have only one instance in the system
If instance already exists, i will not call 'onCreate' it will call 'onNewIntent' method.
See http://androidsrc.net/android-activity-launch-mode-example/ for better understand about launch modes.
Although setting the launch mode to singleTask will work, use of that launch mode is discouraged. The documentation for launch mode indicates singleTask is "not recommended for general use".
The desired behavior can be achieved using Intent flags FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP:
Intent intent=new Intent(ActivityC.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
Activity A will not be recreated and will receive the intent via onNewIntent().
Use SingleTask launch mode for Activity A.
New intent will be delivered to existing instance.
I have a service that once it completes a task it launches an intent to start an activity from my application. Like this:
Intent i = new Intent(MyService.this, MyActivityToBringToFront.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
//i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
This service can be running even after my application has been closed. When this is the case and my application is closed I need it to bring the activity to the front of whatever the user is currently doing. So if the user is in a different app I need my activity to pop up in front. Is this possible. None of the flags had any effect. Basically I need it to be like the system phone application. When you get a phone call it always brings the phone to the front. How can I do this? Thanks!
First of all you need to keep context in memory to make intent's.
Secondary you need a mechanism that can re-obtaining your context every 24 hours because usually context stay alive in 24 hours.
After.
Launching Activity from service :
Intent dialogIntent = new Intent(getBaseContext(), myActivity.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
source : https://stackoverflow.com/a/3607934/2956344
To push activity on top add
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Intent i = new Intent();
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setAction("android.intent.action.VIEW");
i.setComponent(ComponentName.unflattenFromString("com.example.package/com.example.package.activityName"));
startActivity(i);
Intent i = new Intent(MyService.this, MyActivityToBringToFront.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity( i);
And API reference is
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
For example, consider a task consisting of the activities: A, B, C, D.
If D calls startActivity() with an Intent that resolves to the
component of activity B, then C and D will be finished and B receive
the given Intent, resulting in the stack now being: A, B.
The currently running instance of activity B in the above example will
either receive the new intent you are starting here in its
onNewIntent() method, or be itself finished and restarted with the new
intent. If it has declared its launch mode to be "multiple" (the
default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same
intent, then it will be finished and re-created; for all other launch
modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be
delivered to the current instance's onNewIntent().
This launch mode can also be used to good effect in conjunction with
FLAG_ACTIVITY_NEW_TASK: if used to start the root activity of a task,
it will bring any currently running instance of that task to the
foreground, and then clear it to its root state. This is especially
useful, for example, when launching an activity from the notification
manager.
launching an activity from a service isn't always a good idea. You may want to use notification for that. If the user clicks on the notification, thats the time you show the Activity.
So I have an abstract class extended through the entire app that overrides the back key to reorder Activity A to the front (With the flag).
So, it would be:
A > B > anywhere, and the back key should bring me back to A
I'm using the FLAG_ACTIVITY_CLEAR_TOP, but it is entirely refreshing A for some reason and I don't want that.
So: Flag_activity_clear_top is reloading the onCreate() rather than onResume(). What gives?
If you want the activity to just be brought to the top without restarting it set the launchMode of the activity to singleTop in the manifest. You will receive a call to onNewIntent when the activity is being brought to the top. onNewIntent is called before onResume. If you only want this behavior for the specific intent you can add the FLAG_ACTIVITY_SINGLE_TOP(in addition to FLAG_ACTIVITY_CLEAR_TOP) to the intent with the addFlags call instead of the manifest.
Intent intent = new Intent(CurrentActivity.this, ActivityNeedOnTop.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
CurrentActivity.this.finish();
From the API docs for FLAG_ACTIVITY_CLEAR_TOP
For example, consider a task consisting of the activities:
A, B, C, D. If D calls startActivity() with an Intent that
resolves to the component of activity B, then C and D
will be finished and B receive the given Intent,
resulting in the stack now being: A, B.
**The currently running instance of activity B in the above example
will either receive the new intent you are starting here in its
onNewIntent() method, or be itself finished and restarted with the new intent.**
So I think your activity is itself finished and restarted.
I'm using flag FLAG_ACTIVITY_SINGLE_TOP and FLAG_ACTIVITY_CLEAR_TOP to go back to my previous "standard" activity. I use FLAG_ACTIVITY_SINGLE_TOP to prevent re-creating a new instance. But what I found is that the flag FLAG_ACTIVITY_SINGLE_TOP is neglected and the activity is finished and re-created.
Here is what I found in docs. FLAG_ACTIVITY_CLEAR_TOP: It says that you can add FLAG_ACTIVITY_SINGLE_TOP when using FLAG_ACTIVITY_CLEAR_TOP to prevent "finish - recreate".
Here is another doc. FLAG_ACTIVITY_CLEAR_TOP:
Note: If the launch mode of the designated activity is "standard", it too is removed from the stack and a new instance is launched in its place to handle the incoming intent. That's because a new instance is always created for a new intent when the launch mode is "standard".
Did I misunderstand the first doc?
The documentation suggests that FLAG_ACTIVITY_CLEAR_TOP is all you need to set. But you actually HAVE to set both to prevent the activity from being created again.
This did the trick in my case: (Main being the activity that I wanted to return to)
Intent tabIntent = new Intent(this, Main.class);
tabIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(tabIntent);
This one could be helpful: Android Intent.FLAG_ACTIVITY_SINGLE_TOP AND Intent.FLAG_ACTIVITY_CLEAR_TOP
Check this one.
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED|Intent.FLAG_ACTIVITY_SINGLE_TOP)