What is difference between using Intent flag "CLEAR_TOP" and launchMode="singleTask"? - android

What is difference between using Intent flag "FLAG_ACTIVITY_NEW_TASK" & "FLAG_ACTIVITY_CLEAR_TOP" and launchMode="singleTask"? and What is the difference in setting intent flag as FLAG_ACTIVITY_SINGLE_TOP and setting launchMode to "singleTop".

I understood your question from your comment you replied to Tim. So you want to know the
behavior differences when setting launchModes and when setting
Intentflags to an activity
Answer to your this question is that you set launchMode for an Activity inside AndroidManifest.xml file but the particular launch behavior can be changed in some ways at runtime through the Intent flags FLAG_ACTIVITY_SINGLE_TOP, FLAG_ACTIVITY_NEW_TASK, and FLAG_ACTIVITY_MULTIPLE_TASK etc.
Now lets come to your two more questions that you mentioned in your main question.
What is difference between using Intent flag "FLAG_ACTIVITY_NEW_TASK"
& "FLAG_ACTIVITY_CLEAR_TOP" and launchMode="singleTask"?
FLAG_ACTIVITY_NEW_TASK
When we set this flag through intent and launch that activity. In that case that 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. It means it will create a separate history stack. For example, in your app you have a settings icon, when you click on that you go to settings activity where you have further activities. Here all the actions recorded will start from your setting activity only.
FLAG_ACTIVITY_CLEAR_TOP
As its name is telling clearly, if you start an Activity with this flag in a existing task(please understand task then everything will be very easy to understand), in that case all the activities in stack above this activity will be closed and this will become the last activity or oldest activity in the Task.
singleTask
When you start an activity for which you set launchMode = "singleTask" and there is already a task running that starts with this activity, then instead of starting a new instance the current task is brought to the front.
Your seconde question
What is the difference in setting intent flag as
FLAG_ACTIVITY_SINGLE_TOP and setting launchMode to "singleTop"?
FLAG_ACTIVITY_SINGLE_TOP and lanuchMode = "singleTop"
Both are have same behavior, flag is set at runtime and launchMode in AndroidManifest.xml in the beginning. The behavior is, activity this with this will be the only activity on the top in a Task. If it is already running at the top of the history stack then the activity will not be launched again.
NOTE: the best way to understand the behavior is to follow any tutorial and check it practically. Play around with code and see the behavior.
Here are some useful links:
Launch Modes : https://developer.android.com/reference/android/R.styleable#AndroidManifestActivity_launchMode
Intent flags : https://developer.android.com/reference/android/content/Intent

I think the Android documentation https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_CLEAR_TOP of FLAG_ACTIVITY_CLEAR_TOP explains the difference quite well. The launch modes are quite nicely explained at https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en.

Related

How to recreate recent-apps activity when app is launched from notification

My app and activity is in my list of recent apps when I receive a notification. When I click on the notification, I want the intent of the notification to be honored. In my case I want to restart the activity (brute force) and pass in the new intent: so, finish then re-create. I am reading about such tags as FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_SINGLE_TOP but I don't understand them enough to know how to force a "finish then re-create` of my activity. And, oh, the activity in question is MainActivity.
The snippet inside GcmListenerService uses
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
for sending the notification intent
Alternatively
If I go with onNewIntent things get complicated because there maybe DialogFragments being displayed, etc. And I would have to clear everything. That is why finish then re-create seem like the simplest solution to me.
Intent flag FLAG_ACTIVITY_CLEAR_TOP should produce the desired behavior. The documentation for Tasks and Back Stack says this in the section for Using Intent Flags:
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".
The documentation for FLAG_ACTIVITY_CLEAR_TOP describes the same behavior in more detail.

Android - Bring an activity to the front from application class

I am trying to bring an activity to the front. I found many questions similar to this but none of them actually works.
I always hold a reference to the current activity in a variable in application class. While the application is running in the background (after onPause fires), if any message arrives, I need to bring the same activity to the front and display the message. The only way I got it worked is..
Intent i = new Intent(mCurrentActivity, JoboffersActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
The issue I have got with this, is that it recreates the activity which I wanted to avoid. I tried singleInstance and singleTask both in the manifest. If I do not add FLAG_ACTIVITY_CLEAR_TOP, on back key press it takes me to the previous instance of the same activity. Even if I add sigleInstance it creates two instances of the same activity. If I do not add FLAG_ACTIVITY_NEW_TASK then it shows an error Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag
Try to add another flag FLAG_ACTIVITY_SINGLE_TOP to your intent.
According to Android documentation, combination of this 2 flags:
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
brings the current instance of Activity to the front.
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP

What Are the Differences Between FLAG_ACTIVITY_RESET_TASK_IF_NEEDED and FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP?

I am in the process of (finally) writing the chapter on tasks for my book, and I am encountering a few lingering puzzles.
Things that serve as home screen launchers seem to use the combination of FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_RESET_TASK_IF_NEEDED when they launch the requested launcher activity:
Intent i=new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
i.setComponent(name);
startActivity(i);
The documentation for FLAG_ACTIVITY_RESET_TASK_IF_NEEDED has:
If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.
That's not especially clear.
In particular, it would seem that the same effects would be seen using a combination of FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP. Quoting the docs for FLAG_ACTIVITY_CLEAR_TOP:
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...
The currently running instance of [the desired activity] 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().
The FLAG_ACTIVITY_CLEAR_TOP documentation makes sense, at least to me.
So, what does FLAG_ACTIVITY_RESET_TASK_IF_NEEDED do that is different than the combination of FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP?
Bonus points if you can explain what FLAG_ACTIVITY_CLEAR_TASK does that is different from either of the other two options described above.
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.
One obvious difference between this and FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP is that FLAG_ACTIVITY_CLEAR_TASK needs FLAG_ACTIVITY_NEW_TASK. But, other than that, it would seem like the net effects are the same, and also match FLAG_ACTIVITY_RESET_TASK_IF_NEEDED.
I had a look at the source code for the ActivityManager. The flag Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED does indeed do some magic that Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP does not do: It triggers task reparenting.
Here's an (albeit lame) example:
In App A we have the root Activity RootA and we have another Activity ReparentableA:
<application
android:label="#string/app_name">
<activity android:name=".RootA">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ReparentableA"
android:allowTaskReparenting="true"/>
</application>
App A has the package name "com.app.a" so the default taskAffinity of its components is "com.app.a".
In App B we have the root Activity RootB:
<application
android:label="#string/app_name">
<activity android:name="RootB">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
App B has the package name "com.app.b" so the default taskAffinity of its components is "com.app.b".
Now we launch App B from the HOME screen. This starts a new task and creates a new instance of Activity RootB as the root Activity in that task. Activity RootB now launches Activity ReparentableA in the standard way, without any special flags. An instance of ReparentableA is created and put on top of RootB in the current task.
Press HOME.
Now we launch App A from the HOME screen. This starts a new task and creates a new instance of Activity RootA as the root Activity in that task. NOTE: When Android launches a "launcher" Intent, it automatically sets the flags Intent.FLAG_ACTIVITY_NEW_TASK and Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED. Because of this, launching RootA now triggers task reparenting. Android looks to see if there are any activities in any other tasks that have an affinity for this new task (and are reparentable). It finds ReparentableA (which has the same task affinity as RootA) in the App B task and moves it to the new App A task. When launching App A we do not see RootA, we actually see ReparentableA, as it is moved to the top of the new task.
If we return to App B, we can see that ReparentableA is gone from the task stack and that task now consists of only one Activity: RootB.
Notes about using Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP
The important thing to remember about using these flags to "reset a task" is that it only works if there is already an instance of the target Activity at the root of the task. If your root Activity ever finishes, you cannot clear your task by starting the root Activity with Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP. Android will just create a new instance of the target (root) Activity and put it on top of the existing activities in the task, which is probably not at all what you want.
Difference between Intent.FLAG_ACTIVITY_CLEAR_TASK and Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP:
As noted above, using CLEAR_TOP | SINGLE_TOP only works if there is already an instance of the target Activity in the task. CLEAR_TASK, however, removes all activities from the task, regardless of whether or not there was an instance of the target Activity in the task. Also, using CLEAR_TASK ensures that the target Activity becomes the root Activity of the task, without you needing to know what Activity was the root Activity before you cleared the task.
Difference between Intent.FLAG_ACTIVITY_CLEAR_TASK and Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:
As indicated above, using CLEAR_TASK will always remove all activities from the task and launch a new instance of the target activity. In contrast, RESET_TASK_IF_NEEDED will only reset the task in certain situations (the "IF_NEEDED" part). The task is only "reset" if Android is either:
Creating a new task (in which case the "reset" functionality involves the task reparenting explained above), or
If Android is bringing a background task to the foreground (in which case the task is only cleared of any activities that were launched with Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET and any activities that are on top of those activities). NOTE: The root Activity is never cleared in this case.
IMPORTANT NOTE: When you are testing, please note that there is a difference in the way Android behaves when launching apps from the HOME screen (or from the list of available applications) and when selecting tasks from the recent task list.
In the first case (launching an app by selecting it from the list of available applications or from a shortcut on the HOME screen), a launcher Intent with Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED is created. This is used regardless of whether or not the app is already running. The Intent is launched and then the ActivityManager figures out what to do.
In the second case (selecting a task from the list of recent tasks), if the task still exists, it is just brought the front. The task "reset" is NOT performed if the task is just brought to the front using the recent task list. It isn't obvious to me how this is managed and I've not had a chance to look through the source code to figure out why that is.
I hope this answers your questions. Looking forward to your feedback and test results.
I might be mistaken here, but in my understanding FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED does analyze all tasks and makes sure that only one task with launcher activity is running.
FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP will inspect current task only, so you might end up with 2 launcher instances running at the same time (if the first one was created as a separate task).
1) FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
If some task is pending,than it will destroy that process and will start the activity that you requested
2) FLAG_ACTIVITY_CLEAR_TOP
If any previous intent of this activity is running,than this method will deliver the running instance of the activity,close all other activities and will start activity with previous instance.
3) FLAG_ACTIVITY_SINGLE_TOP
If recently this activity has been launched,and instance is saved,than it will not launch this activity.

Multiple Instances of an Activity

I am trying to show the user information on incoming-call screen, whenever there is an incoming-call. So I have a broadcast receiver listening to incoming calls, which starts the intent service, which subsequently starts an activity (with Theme Dialog).
Now, whenever there is an incoming-call, my activity dialog pops up and shows as intended.
Problem: When the activity dialog is already on the screen and incoming-call happens, there is no new activity dialog with new information. I guess that whenever there is an instance, Android does not creates the new one. So it seems like my problem is "creating multiple instances of an activity".
Please note that I am starting an activity from an intent service using FLAG_NEW_TASK.
Google Doc says :
FLAG_ACTIVITY_NEW_TASK
"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."
So, if you want to start a new fresh activity then simply not use this flag only, you should use it with FLAG_ACTIVITY_CLEAR_TASK for the desired result.
For Example:
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
If the above solution is not what you needed, then have a look at
android:launchMode attribute, declare this attribute with the desired options (i.e. as per your need) in activity tag of manifest file.
Hope this will solve the problem.
Use flag FLAG_ACTIVITY_MULTIPLE_TASK which according to the documentation :
Used in conjunction with FLAG_ACTIVITY_NEW_TASK to disable the behavior of bringing an existing task to the foreground. When set, a new task is always started to host the Activity for the Intent, regardless of whether there is already an existing task running the same thing.
Using this flag along with FLAG_ACTIVITY_NEW_TASK will cause each activity instance to be created as a separate task and thus you can have different dialog pop ups.
Simply add following flags to your Intent .
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK);

Android intent parameter FLAG_ACTIVITY_SINGLE_TASK missing?

I have just noticed that parameter FLAG_ACTIVITY_SINGLE_TASK is no more available in the Android developer documentation:
I am just trying to do this:
removeCard.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TASK);
startActivity(removeCard);
I have already seen such a parameter in code found in Google but the Java compiler just tells me it does not exist.
I am only able to start the main activity with this parameter but I have to configure the manifest file to perform this:
android:launchMode = "singleTask"
And this does not work for activities other than main activities launched upon app start.
Does someone know why this parameter disappear for Intent ?
Regards,
Franz
Ok so after having a look around, I managed to figure out that there is no such things as FLAG_ACTIVITY_SINGLE_TASK or FLAG_ACTIVITY_SINGLE_INSTANCE, nor has there even been. This is because you are looking for values which can only be defined through the application's launch mode which is defined in the manifest. Only FLAG_ACTIVITY_SINGLE_TOP is available as an intent flag. Therefore if you want to make use of any of the singleTask, singleInstance, singleTop or standard launch modes, they must be defined in the manifest:
<activity
android:name="com.company.ActivityName"
android:launchMode="singleTask">
</activity>
See the launchMode section in the documentation: http://developer.android.com/guide/topics/manifest/activity-element.html
android:launchMode = "singleTask" should work for all activities when used correctly and are you sure you're not referring the FLAG_ACTIVITY_SINGLE_TASK which is still present and appears to do what you are wanting.
public static final int FLAG_ACTIVITY_SINGLE_TOP
Since: API Level 1 If set, the activity will not be launched if it is
already running at the top of the history stack.
No it is not missing. From developer docs......Using Intent flags
FLAG_ACTIVITY_NEW_TASK
Start the activity in a new task. If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent in onNewIntent().
This produces the same behavior as the "singleTask" launchMode value, discussed in the previous section.
That means FLAG_ACTIVITY_NEW_TASK do the same as Singletask do

Categories

Resources