Resume the Activity instead of Starting if already exists in back stack - android

I have an Activity_1 after a lot of steps, say
Activity_2 > Activity_3 .... in some Activity_n I change some data related to Activity_1 and call it using
Intent intent = new Intent(Activity_n.this, Activity_1.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
To refresh the content. But later I can go all the way back to Activity_1 where I started, which has old data.
Instead I want the initial Activity_1' s onResume() to be called, using the above code. Or appropriate Flag
FLAG_ACTIVITY_CLEAR_TOP
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.
That' what the docs say, but not what I am getting.

You can add this two lines and try
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Write this in your manifest file inside Activity
<activity
android:name=".SettingsActivity"
android:launchMode="singleInstance"
android:screenOrientation="portrait" >
</activity>
"singleTask" and "singleInstance" activities can only begin a task. They are always at the root of the activity stack. Moreover, the device can hold only one instance of the activity at a time — only one such task.
You can use SingleTask or SingleInstance
"singleTask" - The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.
"singleInstance" - Same as "singleTask", except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task.
Refer this link http://developer.android.com/guide/topics/manifest/activity-element.html

intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Visit : http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_REORDER_TO_FRONT

Resume Activity from backstack if exists or create a new one if not
android:launchMode="singleTask"
add this line to your app's AndroidManifest.xml and start the activity with a normal Intent.

Related

Should I use FLAG_ACTIVITY_CLEAR_TOP in this case? how to use FLAG_ACTIVITY_CLEAR_TOP intent flag?

In my app I have the following Activity flow:
LoginActivity > DashboardActivity > (if user opts to change their password) > ChangePasswordActivity
If the user successfully changes their password, I'd like to send them back to the very first Activity which is LoginActivity. I would like to pop DashboardActivity in the process to prevent any unwanted lingering Activities.
Is it correct to use FLAG_ACTIVITY_CLEAR_TOP to start a new LoginActivity in this case? I'd like to know which flags are appropriate in this scenario.
For what it's worth, my DashboardActivity has a launchMode set to singleTop in my AndroidManifest.
If you want to just clear the previous activities from stack and
launch login activity just do this
in manifest file your login activity should be like this
<activity
android:name=".LoginActivity"
android:screenOrientation="portrait"/>
After changing password launch the login activity with following tags
Intent intent = new Intent(ChangePassword.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
By setting flag to Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
all the previous activities will be cleared from stack.
for more info check this
https://developer.android.com/reference/android/content/Intent
From the official documentation - 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.
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.
LoginActivity > DashboardActivity > (if user opts to change their password) > ChangePasswordActivity
In order to clear task and intent to LoginActivty you should use
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Is it correct to use FLAG_ACTIVITY_CLEAR_TOP to start a new LoginActivity in this case? I'd like to know which flags are appropriate in this
FLAG_ACTIVITY_CLEAR_TOP will clear everything from the stack and make
the new activity as root task. In your case, there is no previous
activity for LoginActivity it will also work but not advisable.
For what it's worth, my DashboardActivity has a launchMode set to singleTop in my AndroidManifest.
It will not be useful in your case though you get detail of “LaunchMode" here https://blog.mindorks.com/android-activity-launchmode-explained-cbc6cf996802
Also check
https://blog.mindorks.com/android-task-and-back-stack-review-5017f2c18196
for details

singleTask mode & task back stack

Could please someone give me an example of how we can create a task back stack with having an Activity, which has launchMode=singleTask, at top of the stack and it's not the only activity in the back stack.
For example, we have one such task in the below diagram (the one including Activity X & Y);
As far as I know, singleTask activity is supposed to be the root one and task elements can never be rearranged.
Thanks in advance
Create an app Application1 with four Activities:
Activity1
Make sure that it is not exported="false" (that is, it's true either explicitly or implicitly)
Make it the launcher
Activity2
ActivityX
ActivityY
It's the one: launchMode="singleTask"
In Activity1 implement two actions, e.g. two distinct buttons each doing the following:
Start Activity2 and finish itself
Start Activity2 and do not finish itself
In Activity2 implement two actions:
Start ActivityX and finish itself
Start ActivityY and do not finish itself
In ActivityX implement one action:
Start ActivityY and do not finish itself
ActivityY do nothing :)
Create another app Application2 with an Activity:
AnotherActivity
Make it the launcher
In AnotherActivity implement one action:
Start Activity1. You can do it like this:
Intent intent = new Intent();
// package, fully qualified class name
intent.setComponent(new ComponentName(
"com.stackoverflow", "com.stackoverflow.Activity1");
startActivity(intent);
Launch Application1, which will start Activity1
In Activity1, start Activity2 finishing itself
In Activity2, start ActivityX finishing itself
In ActivityX, start ActivityY
Press home
Launch Application2, which will start AnotherActivity
In AnotherActivity, start Activity1
In Activity1, start Activity2 without finishing itself
In Activity2, start ActivityY without finishing itself
There you go. Pop the stack with the back button now.
Actually, this is pretty easy to do.
To generate a task that contains X at the root and Y on top, even though Y is declared with launchMode="singleTask":
<application android:label="#string/app_name" android:icon="#drawable/ic_launcher">
<activity android:name=".X">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".Y" android:launchMode="singleTask"/>
</application>
In activity X just launch activity Y like this:
startActivity(new Intent(this, SingleTaskActivity.class));
You will now have a task with activity X at the root and activity Y on top of that.
This happens even if you explicitly say that you want Y launched in a new task, like this:
Intent intent = new Intent(this, SingleTaskActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
This seems counter-intuitive, but the reason is because both X and Y have the same taskAffinity. And taskAffinity trumps launchMode when Android needs to decide how to launch an Activity.
taskAffinity, if not specifically set, defaults to the package name of the application. All activities with the same taskAffinity will be launched into the same task.
This confuses most developers, because the documentation doesn't mention taskAffinity very often.
If you really want to be sure that an Activity will always be the root of its task, no matter how it is launched, you need to use either launchMode="singleTask" or launchMode="singleInstance" and specify taskAffinity="" to indicate that the Activity has no task affinity (ie: it doesn't belong with any other activities).

Could an activity with single task flag be cleared via clear top?

Assume that I have a launcher activity A which has singleTask launch mode. Now imagine that A starts Activity B like;
Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, REQ_ACCOUNT_ACTIVITY);
In this case it seems like A's not destroyed. I wonder if it's correct or did I something wrong?
You can achieve this by using below attribute in AndroidMenifest file
android:finishOnTaskLaunch="true"
<application
...
>
<activity
android:finishOnTaskLaunch="true"
android:launchMode="singleTask"
...>
</activity>
</application>
If you not want to kept new activity in the history stack. Use below one_
FLAG_ACTIVITY_NO_HISTORY
//Actvity B is not in BackStack if we set FLAG_ACTIVITY_NO_HISTORY flag
Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivityForResult(intent, REQ_ACCOUNT_ACTIVITY);
As soon as the user navigates away from Activity B, the activity is finished. This may also be set with the noHistory attribute.
For more -> Tasks and Back Stack
It's been a while but I came across my own question when I was wandering over here.
The activity A was not getting deleted because the flags are set for the activity B. And when I call this code, there's no such activity called B in the task stack already. So effectively, nothing to clear on top of B.
Hope this helps.

FLAG_ACTIVITY_CLEAR_TOP calls onCreate() instead of onResume()

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.

Clear all activities in a task?

I have a splash screen activity, then a login activity. My history stack looks like:
SplashActivity
LoginActivity
when the user successfully logs in via LoginActivity, I want to start WelcomeActivity, but clear the entire stack:
SplashActivity
LoginActivity // launches WelcomeActivity ->
WelcomeActivity
// but now all three are in the history stack, while I only
// want WelcomeActivity in the stack at this point.
Is there some flag I can use to do that?
// LoginActivity.java
Intent intent = new Intent(this, WelcomeActivity.class);
intent.addFlag(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
Not sure if using the FLAG_ACTIVITY_CLEAR_TASK will clear out all activities in my task or not. I can do this 'manually' by unwinding the stack by using startActivityForResult() calls, but will be more fragile and more code to maintain.
Thanks
Yes that should work fine. You could use:
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_CLEAR_TASK
FLAG_ACTIVITY_NEW_TASK
which ensures that if an instance is already running and is not top then anything on top of it will be cleared and it will be used, instead of starting a new instance (this useful once you've gone Welcome activity -> Activity A and then you want to get back to Welcome from A, but the extra flags shouldn't affect your case above).
Intent intent = new Intent(this, NextActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Use android:noHistory="true" on the splash activity in the manifest file.
<activity
android:name=".activity.SplashActivity"
android:theme="#style/theme_noActionBar"
android:noHistory="true">
finish() removes the activity from the stack. So, if you start LoginActivity and call finish() on SplashActivity, and then you do exact the same to start WelcomeActivity you will get the desired behaviour. No need to use extra flags.
Intent.FLAG_ACTIVITY_NO_HISTORY can work in your case too if you do not want the activity on the history stack.
Just do this to clear all previous activity in a task:
finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
In case that all of three activity is involved in the same app(same taskAffinity), you can pick either 1,2 or 3 below. otherwise you should pick 1,2 below.
If you don't want to return back SplashActivity from LoginActivity, you can define activity attribute noHistory in AndroidManifest.xml or you can set FLAG_ACTIVITY_NO_HISTORY into the intent to launch SplashActivity. if SplashActivity is started from Launcher, you should pick way to set activity attribute noHistory.
If you don't want to return back LoginActivity from WelcomeActivity, you can use either activity attribute noHistory or FLAG_ACTIVITY_NO_HISTORY like number 1 above.
If you want to clear back stack on specific situation, you can use FLAG_ACTIVITY_CLEAR_TASK in conjunction with FLAG_ACTIVITY_NEW_TASK(FLAG_ACTIVITY_CLEAR_TASK always must be used in conjunction with FLAG_ACTIVITY_NEW_TASK). But, if the activity being started is involved in other app(i.e different taskAffinity), the task will be launched other task after the task is cleared, not current task. so make sure that the activity being launched is involved in the same app(taskAffinity).

Categories

Resources