How to reset all activities and launch a new one? - android

I have an application in which i want to navigate this way:
A -> B -> C
And from C launch a new activity called D, that goes to top and also clears the task, meaning that if i press back on D it goes to home screen.
If i understand it correctly this FLAG: FLAG_ACTIVITY_TASK_ON_HOME does this... but it's only on current APIs (11>).
I'm developing for Android 1.5> how can i also have this behaviour?
Thanks!

you are looking for this:
Intent intent = new Intent(activity, activityClass);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
activity.startActivity(mainIntent);
use android compatibillity lib from google - found in the sdk.
or use finish()

You can use FLAG_ACTIVITY_CLEAR_TASK along with FLAG_ACTIVITY_NEW_TASK.
public static final int FLAG_ACTIVITY_CLEAR_TASK
Since: API Level 11
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.
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TASK

I've ended up using this https://stackoverflow.com/a/8576529/327011 as I needed to use it from 1.5 > and that flag is only avaliable on higher APIs.
If I hadn't the need to support "low" API levels the answer from #aromero would be my option.

Related

How to set no History for all Activities

My Android Application is based on four Activities. The last activity starts an Intent Service and set itself to background.
Before I sent the last Activity to background I would like to remove all four Activities from backstack history
I tried already to set the no history = true attribute for the activities. This causes errors when I use startActivityForResult, so I need a different solution
I don't really think there is an "good" way to do this, I would try something like this:
First create a SelfClosingActivity which only job is to close itself after opening:
public void onCreate(Bundle savedInstanceState()) {
super.onCreate(savedInstanceState);
finish();
}
When you want to close all the Activities (after you start your IntentService I guess) run the SelfClosingActivity and add flags to clear the current stack.
Intent intent = new Intent(this, SelfClosingActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
This will clear the current stack before opening SelfClosingActivity and SelfClosingActivity will close itself leaving the stack completely empty.
FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK will do what you want.
FLAG_ACTIVITY_CLEAR_TOP
Added in API level 1 int 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.
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.
Refer to Tasks and Back Stack for more info

How to get combined behaviour of FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_CLEAR_TASK?

There are so many questions on SO related to this, but no such direct questions I could find.
My app has a main activity M, and a sub activity S.
M launchMode is singleTask because I only ever want one instance running and I want S to exist in the same task as M.
S launchMode is standard, because it can have many instances.
In S, there is an Up button which must always take the user to M.
There are two types of task stack (with S on top):
MSSSS...S
If the user presses Up in S, then the stack should become:
M (where M should be in the same state the user left it)
SSSS...S
If the user presses Up in S, then the stack should become:
M (a new instance)
--
So how to construct the Intent for the Up button...
In the first case, FLAG_ACTIVITY_CLEAR_TOP should do the trick, but if we apply this to the second case then the user is dumped back in Home.
In the second case, FLAG_ACTIVITY_CLEAR_TASK will do the trick, but if we apply this to the first case, we discover that M is finished and restarted.
One might also be tempted to try FLAG_ACTIVITY_NEW_TASK, but then we find hitting Back from M will take the user to the screen where he/she hit Up.
Side note: how is this possible when M is singleTask and the activities all have the same (default) task affinity?
So how to correctly construct the Up Intent in this case?
You cannot construct an UP Intent that will do what you want. Those things are mutually exclusive. What you could do is the following:
Change launch mode of M to singleTop
In M.onCreate(), check if M is at the root of the task by using isTaskRoot(). If it isn't the task root, have M restart itself and clear the task as follows:
Intent relaunch = new Intent(this, M.class);
relauch.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(relaunch);
In your UP Intent, add the following flags: Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP.
This will ensure that if an instance of M already exists in the task, it will clear everything on top of that instance and call onNewIntent() on the existing instance.
If there isn't an existing instance of M in the task, it will launch a new instance on top of the stack. This instance will recognize that it isn't the root activity and it will clear the task and relaunch itself.
Note: This will only work on Android 3.0 and above (API 11 or higher).
Here is a workaround/hack using a (Lollipop) deprecated API:
ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
if (M_CLASS_NAME.equals(am.getRunningTasks(1).get(0).baseActivity.getClassName()) {
// we should be able to just clear top - because M is already running
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
else {
// okay to assume M is not running (because it is always root of task)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
}

Kill all instances of an Activity

I'm setting up Notifications in my app and I've noticed whilst testing, after clicking a new notifications (in this case the notification loads a blog details page), I have many instances of the blog details activity running (pressing back it shows each activity with the previously loaded blogs).
Is it possible in my Receiver class, so look if there is any instance of ActivityBlog already running, and if there all .finish() them all so there is only ever once instance running?
I found this but I couldn't work out a way to do it from that.
You should study activity launch modes
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
Use android:launchMode="singleTop" in element in manifest file.
You will get callback in onNewIntent() if an instance of activity is already up. Stack of your activities will be automatically updated and there wont be any need of killing activities which is consumes time and resources.
This i believe is the recommended approach.
Intent z = new Intent(Projects_Accel.this,MainActivity.class);
z.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_CLEAR_TASK |
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(z);
use this for kill all activity
Do this way
Intent intent = new Intent(this, ActivityBlog.class);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
activity.startActivity(mainIntent);
NOTE:
You need to put android-support.jar in libs folder

Flag similar to FLAG_ACTIVITY_CLEAR_TASK in API 8

My App has an Activity A which triggers B and B in turn triggers C.
Activity A is the launcher with the intent flag android:noHistory="true" in manifest file. This shows the splash screen. After 2 seconds it triggers B with the intent flag FLAG_ACTIVITY_NO_HISTORY. B triggers C normally without any intent flag. Now the Stack will have only the Activity C.
In Activity C, Whenever back is pressed It will trigger Activity B. Now the Stack should have the Activity B alone. It should not have any trace of other Activity.
I have used the following code in the Activity C. But the flag FLAG_ACTIVITY_NEW_TASK is available only from API 11. The app should be supporting the devices from the API 8. Kindly assist me with the correct intent flags to achieve the explained scenario
Code:
Intent dragDropIntent = new Intent("android.intent.action.DRAGDROP");
dragDropIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
dragDropIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
I agree that starting the Activity C without nohistory will help. But do t some technical constraints I don't want to do that. Thanks in Advance
you are looking for this:
Intent intent = new Intent(activity, activityClass);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
activity.startActivity(mainIntent);
use android compatibillity lib from google - found in the sdk.
or use finish()
This flag is now available through the compatibility lib:
IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
Hope this helps :)
If C is always goes back to B, then you should not use FLAG_ACTIVITY_NO_HISTORY. Then when the user backpress in C, C would be finished by the OS and the stack now only has B.

Clear the entire history stack and start a new activity on Android

Is it possible to start an activity on the stack, clearing the entire history before it?
The situation
I have an activity stack that either goes A->B->C or B->C (screen A selects the users token, but many users only have a single token).
In screen C the user may take an action which makes screen B invalid, so the application wants to take them to screen A, regardless of whether it is already in the stack. Screen A should then be the only item on the stack in my application.
Notes
There are many other similar questions, but I haven't found anything that answers this exact question. I tried calling getParent().finish() - this always results in a null pointer exception. FLAG_ACTIVITY_CLEAR_TOP only works if the activity is already on the stack.
In API level 11 a new Intent Flag was added just for this: Intent.FLAG_ACTIVITY_CLEAR_TASK
Just to clarify, use this:
Java
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Kotlin
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
Unfortunately for API lvl <= 10, I haven't yet found a clean solution to this.
The "DontHackAndroidLikeThis" solution is indeed pure hackery. You should not do that. :)
Edit:
As per #Ben Pearson's comment, for API <=10 now one can use IntentCompat class for the same. One can use IntentCompat.FLAG_ACTIVITY_CLEAR_TASK flag to clear task. So you can support pre API level 11 as well.
Case 1:Only two activity A and B:
Here Activity flow is A->B .On clicking backbutton from B we need to close the application then while starting Activity B from A just call finish() this will prevent android from storing Activity A in to the Backstack.eg for activity A is Loding/Splash screen of application.
Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();
Case 2:More than two activitiy:
If there is a flow like A->B->C->D->B and on clicking back button in Activity B while coming from Activity D.In that case we should use.
Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
Here Activity B will be started from the backstack rather than a new instance because of Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_NEW_TASK clears the stack and makes it the top one.So when we press back button the whole application will be terminated.
With Android's Newer Version >= API 16 use finishAffinity()
approach is suitable for >= API 16.
Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
Its is same as starting new Activity, and clear all stack.
OR Restart to MainActivity/FirstActivity.
I spent a few hours on this too ... and agree that FLAG_ACTIVITY_CLEAR_TOP sounds like what you'd want: clear the entire stack, except for the activity being launched, so the Back button exits the application. Yet as Mike Repass mentioned, FLAG_ACTIVITY_CLEAR_TOP only works when the activity you're launching is already in the stack; when the activity's not there, the flag doesn't do anything.
What to do? Put the activity being launching in the stack with FLAG_ACTIVITY_NEW_TASK, which makes that activity the start of a new task on the history stack. Then add the FLAG_ACTIVITY_CLEAR_TOP flag.
Now, when FLAG_ACTIVITY_CLEAR_TOP goes to find the new activity in the stack, it'll be there and be pulled up before everything else is cleared.
Here's my logout function; the View parameter is the button to which the function's attached.
public void onLogoutClick(final View view) {
Intent i = new Intent(this, Splash.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
}
Immediately after you start a new activity, using startActivity, make sure you call finish() so that the current activity is not stacked behind the new one.
You shouldn't change the stack. Android back button should work as in a web browser.
I can think of a way to do it, but it's quite a hack.
Make your Activities singleTask by adding it to the AndroidManifest
Example:
<activity android:name=".activities.A"
android:label="#string/A_title"
android:launchMode="singleTask"/>
<activity android:name=".activities.B"
android:label="#string/B_title"
android:launchMode="singleTask"/>
Extend Application which will hold the logic of where to go.
Example:
public class DontHackAndroidLikeThis extends Application {
private Stack<Activity> classes = new Stack<Activity>();
public Activity getBackActivity() {
return classes.pop();
}
public void addBackActivity(Activity activity) {
classes.push(activity);
}
}
From A to B:
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class);
startActivity(this, B.class);
From B to C:
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class);
startActivity(this, C.class);
In C:
If ( shouldNotGoBackToB() ) {
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.pop();
}
and handle the back button to pop() from the stack.
Once again, you shouldn't do this :)
Advanced Reuseable Kotlin:
You can set the flag directly using setter method. In Kotlin or is the replacement for the Java bitwise or |.
intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
If you plan to use this regularly, create an Intent extension function
fun Intent.clearStack() {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
You can then directly call this function before starting the intent
intent.clearStack()
If you need the option to add additional flags in other situations, add an optional param to the extension function.
fun Intent.clearStack(additionalFlags: Int = 0) {
flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Try below code,
Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_CLEAR_TASK|
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Try this:
Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();
For me none of the above methods not work.
Just do this to clear all previous activity:
finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
In Java: -
startActivity(new Intent(getApplicationContext(),ChooseServiceActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
Sometimes your android emulator might fails to connect eclipse DDMS tool and ask for adb to start manually. In that case you can start or stop the adb using the command prompt.
I found too simple hack just do this add new element in AndroidManifest as:-
<activity android:name=".activityName"
android:label="#string/app_name"
android:noHistory="true"/>
the android:noHistory will clear your unwanted activity from Stack.

Categories

Resources