Android remove Activity from back stack - android

Okay so I'm kind of stumped on what to do with this. So I have the MainActivity, and from there an Activity can be launched to DegreePlanActivity, and from there another Activity can be launched to EditDegreePlan. I've got EditDegreePlan set to noHistory in the AndroidManifest. The problem is after they save the EditDegreePlan it launches an Activity to DegreePlan. So if the user presses Back they have to press it twice to get to MainActivity again. I want to get rid of that so they only have to press it once. I'm stumped on how to do this though.
If I set DegreePlanActivity to noHistory then they couldn't press Back to it while in EditDegreePlan.
I've tried overriding onBackPressed method and launching an intent to MainActivity. The problem then is that they have to press Back multiple times to exit the app then.
What should I do?

FLAG_ACTIVITY_CLEAR_TOP clears your Activity stack , you can use the code below:
Intent intent = new Intent(this, Activity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Remember that this flag clears just Intermediate Activities , for example if you have A,B,C in your Back Stack then going from C Activity to D with this flag this does not clear Back Stack and the Stack would be A,B,C,D but if you go from Activity D to Activity A with this flag , B,C,D Activities will pop up from the stack and you will have just A in the Back Stack .

To remove activity from back stack inside manifest add android:noHistory="true" to your activity inside the manifest file.
See sample below.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.activity"
android:versionCode="1"
android:versionName="1.0">
<application android:name="MyApp" android:label="My Application">
<activity android:name=".LoginActivity"
android:noHistory="true"> //add this line to your activity inside manifest
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

simple solution for API >= 15 to API 23
user activity name in intent.
Intent nextScreen = new Intent(currentActivity.this, MainActivity.class);
nextScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(nextScreen);
ActivityCompat.finishAffinity(currentActivity.this);

I would suggest that you use startActivityForResult(), instead of simply startActivity(), when you launch the EditDegreePlan-Activity, as described in the Android tutorials.
In the EditDegreePlan-Activity you then call
setResult(RESULT_OK);
finish();
If you don't expect any data from the EditDegreePlan-Activity, then you don't necessarily have to implement the onActivityResult.

It seems, that you will get the desired behavior if you do not specify any flags at all. The back button would just do the right thing. To get an activity closed from within your code use the finish() method it has the same effect as the user pressing the back button. So you will automatically arrive at DegreePlan when you finish the EditDegreePlan, no need to call any Intents either.

You can call finish before you start your new activity. This will remove the current activity from the stack, so when you press back button from the next activity, the first activity will not be called from the stack history.
Intent i = new Intent(MainActivity.this, NextActivity.class);
finish();
startActivity(i);

Here is your flow:
MainActivity --> DegreePlanActivty --> EditDegreePlan--> DegreePlan --> MainActivty
Override these method inside your "DegreePlan"
public void onBackPressed() {
super.onBackPressed();
Intent goToMainActivity = new Intent(getApplicationContext(), MainActivity.class);
goToMainActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Will clear out your activity history stack till now
startActivity(goToMainActivity);
}

use this to clear the stack :
menuIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_TOP);

Intent intent = new Intent(getContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

You can add flags as follows and start Activity, try below code
Intent i = new Intent(activity, Payment.class);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(i);

This code should help you out: It is in Kotlin
private fun verifyIfUserIsLoggedIn(){
val uid = FirebaseAuth.getInstance().uid
if(uid== null){
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
}

Related

How to close all activities in a task without clearing the entire backstack?

Let's say I have activities:
First ----------------- Open
A -> B -> C -> D -> E -> F
I want to call finish on activities C,D,E when F is opened, leaving A, B in the back stack such that when a user hits back from F they arrive at B, and so forth.
I have seen tons of examples of clearing the back stack, or pulling one activity from the back stack and clearing the rest, but every time I try to close a Task I end up with an empty back stack and the back button falls out of the app. I wish there were more info on this specific case, and what the best practice for this is (C,D,E,F is a workflow with API side effects that should not be re-entered once leaving, but falling out of the app on back pressed is also not what I want.)
One option is using startActivityForResult() from B, so C will be opened. Then open the next Activities using FLAG_ACTIVITY_FORWARD_RESULT until you reach F.
Override onBackPressed() in F to call setResult(), so users will go back to B. If you don't call startActivityForResult() again, the user will never again be able to reach Activitys C to F.
You can find a detailed example for using FLAG_ACTIVITY_FORWARD_RESULT in my
answer to another SO post
Suppose you have following A->B->C->D->E activities and when you backpressed from activity E, you does'nt want to see activities C & D.
Then you've to pass intent A to B by using this,
Intent i=new Intent(A.this,B.class);
startActivity(i);
Then you've to pass intent B to C by using this,
Intent i=new Intent(B.this,C.class);
startActivity(i);
Then you've to pass intent C to D by using this,
Intent i=new Intent(C.this,D.class);
startActivity(i);
finish();
Then you've to pass intent D to E by using this,
Intent i=new Intent(D.this,E.class);
startActivity(i);
finish();
At final you get Activity E and after that when you backpressed from E ,you able to go at Activity B and after that A.
Thankyou Happy Coding
The best workaround I could find was flagging the final task with FLAG_ACTIVITY_TASK_ON_HOME which just happens to be the task that was in the backstack at the point of departure, in my case. This isn't exactly an answer to the question, but if you are trying to clear a volatile workflow from the backstack and you don't want the user to "fall out" of your app on backpress subsequently, this is a viable option. See thread on the topic here: Android - Clearing Navigation Backstack
Edit: This code below creates separate application instances which I just noticed; not sure if there is a way to prevent that.
The solution I came up with was using taskAffinity, which you set in the manifest xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.example.app">
<activity
android:name=".activities.SplashActivity"
android:launchMode="singleTop"
android:taskAffinity="#string/affinity_main">
</activity>
<activity
android:name=".activities.MainActivity"
android:launchMode="singleTop"
android:taskAffinity="#string/affinity_main">
</activity>
<activity
android:name=".activities.WorkflowStepOneActivity"
android:launchMode="singleTop"
android:taskAffinity="#string/affinity_main">
</activity>
<activity
android:name=".activities.WorkflowStepTwoActivity"
android:launchMode="singleTop"
android:taskAffinity="#string/affinity_workflow">
</activity>
<activity
android:name=".activities.WorkflowStepThreeActivity"
android:launchMode="singleTop"
android:taskAffinity="#string/affinity_workflow">
</activity>
<activity
android:name=".activities.LeaveWorkflowActivity"
android:launchMode="singleTop"
android:taskAffinity="#string/affinity_main">
</activity>
</manifest>
Starting the app the main affinity presumably collects any activities that are started in a task without a declared affinity, but when I want to start a new affinity for my workflow I add new task to the intent:
In MainActivity, or anywhere I call the workflow:
public void startWorkflow() {
Intent intent = new Intent(MainActivity.this,
WorkflowStepOneActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
In intermediate workflow steps we do nothing special:
public void startWorkflowTwo() {
Intent intent = new Intent(MainActivity.this,
LeaveWorkflowActivity.class);
startActivity(intent);
}
Finally, we call finish on the Affinity from our LAST workflow activity, after firing an intent for the post-workflow activity:
public void startWorkflowCompleted() {
Intent intent = new Intent(MainActivity.this,
WorkflowCompletedActivity.class);
startActivity(intent);
finishAffinity();
}
This means our stack will look like this:
SplashActivity -> MainActivity -> LeaveWorkflowActivity

How to logout after killing all activities?

On my App, I have the following process to log on a user:
The user enters its credentials on the MainActivity and is redirected to HomeActivity using that code for navigation:
Intent accueilIntent = new Intent(getApplicationContext(), HomeActivity.class);
accueilIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NEW_TASK);
finish();
startActivity(accueilIntent);
When the user is on the HomeActivity, he is able to log out thanks to a log out button. Since the event is fired, I would like to kill all activities and redirect the user to the login activity (MainActivity). So The code which is fired on the event is the following:
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
The user is well redirected to the MainPage. Then when I press the home button to get back on the Android home screen and then I come back to the App, the right MainActivity appears. However, when I press the native back button to return to the android home screen and then I come back to the App, the HomeActivity appears (the one that should be destroyed before) and not the MainActivity.
Does anyone can tell me why I'm coming back to HomeActivity and not MainActivity in this case?
1] add finish() before startActivity()
2] Add FLAG_ACTIVITY_NO_HISTORY flag.
Intent intent = new Intent(mContext, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
If you want user to come back to MainAcitvity when he presses back button on HomeActivity, the parent of HomeActivity should be MainActivity.
In your manifest.xml file, in HomeActivity's tag add this :
<activity
android:name=".HomeActivity"
android:parentActivityName=".MainActivity" >
....
</activity>

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.

Prevent opening Activity for multiple times

I have a common menu on my app with icons. Clicking an icon will start an Activity. Is there a way to know if an activity is already running and prevent it from starting multiple times (or from multiple entries)? Also can I bring an activity that is in onPause state to the front?
Use this:
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
while starting Activity.
from documentation:
If set in an Intent passed to Context.startActivity(), this flag will
cause the launched activity to be brought to the front of its task's
history stack if it is already running.
In your activity declaration in Manifest file, add the tag android:launchMode="singleInstance"
I got it perfectly working by doing the following.
In the caller activity or service (even from another application)
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(APP_PACKAGE_NAME);
//the previous line can be replaced by the normal Intent that has the activity name Intent launchIntent = new Intent(ActivityA.this, ActivityB.class);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(launchIntent);
and in the manifest of the receiver activity (the I want to prevent opening twice)
<activity android:name=".MainActivity"
android:launchMode="singleTask"
>
This works for me :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
from official documentation
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.
also, you can use FLAG_ACTIVITY_NEW_TASK with it.
then the code will be :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
Just use
Intent i = new Intent(ActivityA.this, ActivityB.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
create an instance of your activity which you dont want to start multiple times like
Class ExampleA extends Activity {
public static Activity classAinstance = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
classAinstance = this;
}
}
Now where ever u want to crosscheck i mean prevent it from starting multiple times, check like this
if(ExampleA.classAinstance == null) {
"Then only start your activity"
}
please add this in menifest file
<activity
android:name=".ui.modules.profile.activity.EditProfileActivity"
android:launchMode="singleTask" // <<this is Important line
/>

How to kill an Android activity when leaving it so that it cannot be accessed from the back button?

In an given Android activity, I would like to start a new activity for the user at some point. Once they leave the first activity and arrive at the second, the first activity is stale and I want to remove it completely so it can not be accessed again from the back button.
How is the best way to accomplish this? How do I kill or destroy this activity immediately after the user has launched the new activity?
You just need to call finish()
Intent intent = new Intent(this, NextActivity.class);
startActivity(intent);
finish();
Setting android:noHistory="true" on the activity in your manifest will remove an activity from the stack whenever it is navigated away from. see here
you can use:
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
You can also add android:noHistory="true" to your Activity tag in AndroidManifest.xml.
<activity
...
android:noHistory="true">
</activity>
Yes, all you need to do is call finish() in any Activity you would like to close.
Write this in each "new activity" after you initialized your new intent->
Intent i = new Intent(this, yourClass.class);
startActivity(i);
finish();
Finally, I got a solution!
My Context is:- I want disconnect socket connection when activity destroyed, I tried to finish() activity but it didn't work me, its keep connection live somewhere.
so I use android.os.Process.killProcess(android.os.Process.myPid());
its kill my activity and i used android:excludeFromRecents="true"
for remove from recent activity .
Add this attribute to you activity in manifest file.
android:noHistory="true"
You've below options to remove an activity from the back stack for a particular task.
Call finish() method just after startActivity() like this:
startActivity(new Intent(FirstActivity.this, SecondActivity.class));
finish();
Add an Intent flag like so:
startActivity(new Intent(FirstActivity.this, SecondActivity.class).addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY));
Add noHistory=true in your manifest file for that particular activity
You just need to use below code when launching the new activity.
startActivity(new Intent(this, newactivity.class));
finish();
In Kotlin, you may use this
startActivity(Intent(context, newActivity::class.java))
finish()
Or you can use this also
val intent = Intent(context, newActivity::class.java))
startActivity(intent)
finish()

Categories

Resources