Finish an activity from another activity
Asked Answered
W

10

115

I want to finish one activity from another activity, like:

In Activity [A], on button click, I am calling Activity [B] without finishing Activity [A].

Now in Activity [B], there are two buttons, New and Modify. When the user clicks on modify then pop an activity [A] from the stack with all the options ticked..

But when the user click on New button from Activity [B], then I will have to finish Activity [A] from the stack and reload that Activity [A] again into the stack.

I am trying it, but I am not able to finish Activity [A] from the stack... How can I do it?

I am using the code as:

From Activity [A]:

Intent GotoB = new Intent(A.this,B.class);
startActivityForResult(GotoB,1);

Another method in same activity

public void onActivityResult(int requestCode, int resultCode, Intent intent) {

    if (requestCode == 1)
    {
        if (resultCode == 1) {
            Intent i = getIntent();
            overridePendingTransition(0, 0);
            i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
            finish();

            overridePendingTransition(0, 0);
            startActivity(i);
        }
    }
}

And in Activity [B], on button click:

setResult(1);
finish();
Whore answered 30/4, 2012 at 5:59 Comment(3)
hey, you wanted to finish one activity from another right... then I had posted the answer which is correct. But, why did you vote it down ?Moro
There is a thread with a few nice answers here: #14356231Hamo
Please see this way https://mcmap.net/q/80892/-finish-all-previous-activitiesAllpowerful
N
200
  1. Make your activity A in manifest file: launchMode = "singleInstance"

  2. When the user clicks new, do FirstActivity.fa.finish(); and call the new Intent.

  3. When the user clicks modify, call the new Intent or simply finish activity B.

FIRST WAY

In your first activity, declare one Activity object like this,

public static Activity fa;
onCreate()
{
    fa = this;
}

now use that object in another Activity to finish first-activity like this,

onCreate()
{
    FirstActivity.fa.finish();
}

SECOND WAY

While calling your activity FirstActivity which you want to finish as soon as you move on, You can add flag while calling FirstActivity

intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);

But using this flag the activity will get finished evenif you want it not to. and sometime onBack if you want to show the FirstActivity you will have to call it using intent.

Nitrogenous answered 30/4, 2012 at 6:40 Comment(16)
You are holding a static reference to an activity. This will never go away unless you clear it manually from somewhere -> you are creating a memory leak!Yester
Plus for declaring an activity singleInstance is also not a good practice. This is recommended approach only for Launcher type apps. "singleTop" should be used instead.Yester
It will remove the top activities, which i believe is what @Whore is asking for. if not he can just use the single Top flag. this will bring the old one to top and wont close the old ones but won't create a new instance, it will just rearange the activity stack. I agree that you answer provides an alternative but it requires a cleanup code afterwards which just complicates things.Yester
If you think there can be any changes in my answer that can improve performance and coding style..then please copy my answer..make changes..and post as another answer..and I will surely Upvote and Appreciate it.Nitrogenous
Well its ok, you have my +1 for out-of-the-box thinking :D, i would just change to singleTop. however it still won't be my first choice when doing something similar. by cleanup code i meant a way to get rid of the static reference so there is no memory leaking, but that depends on the app structure.Yester
is it possible without using without using launchMode = "singleInstance".Publicly
Please no one use the first solution, it is completely wrong. You are bypassing the Android framework in a really hacky way whilst creating a zombie object. Use a BroadcastReceiver.Phonate
@S-K' I only see your comments in this thread no any answer, please put your answer too and that would be much help full to all of us.Nitrogenous
Awesome solutions. Worked very well for my problem in which I was going from activities A->B->C and on onBackPressed of C, I was launching new instance of B. But then if I did onBackPressed on that new instance of B, it used to go to the old instance of B instead of old instance of A (what I wanted). So I followed your first method in the onBackPressed of C, and it gave me the behaviour I wanted :) Thanks a ton :)Apocynthion
@Darko About the leak issue you mentioned on the 1st way, if on_Destroy we make the fa = null, then wouldn't the garbage collector delete it from the ram?Ventriloquy
@Darko: You are right. User should take care of the variabe and Null it in case some other method tries to use it.Asyllabic
Accepted but wrong answer. As commented above, this will create a memory leak.Chagall
Work like a charm;)Abramson
In Kotlin I just did FooActivity.me?.finish() and FooActivity.me = null to avoid the leak.Cogswell
The first works, but sometime it happens [Attempt to invoke virtual method 'void android.app.Activity.finish()' on a null object reference] on FirstActivity.fa.finish(); why?Operative
This is a terrible answer. First part holds a static reference to an activity wich is a bad practice. Second part does not finish activityA, it creates a new instance of activityA with Intent.FLAG_ACTIVITY_NO_HISTORY.Cambridgeshire
P
115

That you can do, but I think you should not break the normal flow of activity. If you want to finish you activity then you can simply send a broadcast from your activity B to activity A.

Create a broadcast receiver before starting your activity B:

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context arg0, Intent intent) {
        String action = intent.getAction();
        if (action.equals("finish_activity")) {
            finish();
            // DO WHATEVER YOU WANT.
        }
    }
};
registerReceiver(broadcastReceiver, new IntentFilter("finish_activity"));

Send broadcast from activity B to activity A when you want to finish activity A from B

Intent intent = new Intent("finish_activity");
sendBroadcast(intent);

I hope it will work for you...

Pignus answered 30/4, 2012 at 6:14 Comment(5)
It shows this error "Syntax error on tokens, AnnotationName expected instead" on "registerReceiver(broadcast_reciever, new IntentFilter("finish_activity"));". What's wrong?Otho
"you should not break the normal flow of activity" +1 for thisPhonate
Don't forget to unregister broadcast_receiver with unregisterReceiver()Glenglencoe
Obviously not working if you turn Dev Options->Don't Keep Activities because this solution break normal flowTrojan
This is the solution. nice oneBienne
I
21

This is a fairly standard communication question. One approach would be to use a ResultReceiver in Activity A:

Intent GotoB=new Intent(A.this,B.class);
GotoB.putExtra("finisher", new ResultReceiver(null) {
    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        A.this.finish();
    }
});
startActivityForResult(GotoB,1);

and then in Activity B you can just finish it on demand like so:

((ResultReceiver)getIntent().getExtra("finisher")).send(1, new Bundle());

Try something like that.

Inspectorate answered 30/4, 2012 at 6:15 Comment(1)
+1 just , ((ResultReceiver)getIntent().getParcelableExtra("finisher")).send(1, new Bundle());Gd
J
12

There is one approach that you can use in your case.

Step1: Start Activity B from Activity A

startActivity(new Intent(A.this, B.class));

Step2: If the user clicks on modify button start Activity A using the FLAG_ACTIVITY_CLEAR_TOP.Also, pass the flag in extra.

Intent i = new Intent(B.this, A.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("flag", "modify");
startActivity(i);
finish();

Step3: If the user clicks on Add button start Activity A using the FLAG_ACTIVITY_CLEAR_TOP.Also, pass the flag in extra. FLAG_ACTIVITY_CLEAR_TOP will clear all the opened activities up to the target and restart if no launch mode is defined in the target activity

Intent i = new Intent(B.this, A.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("flag", "add");
startActivity(i);
finish();

Step4: Now onCreate() method of the Activity A, need to retrieve that flag.

String flag = getIntent().getStringExtra("flag");
if(flag.equals("add")) {
    //Write a code for add
}else {
    //Write a code for modifying
}
Jea answered 30/4, 2012 at 6:44 Comment(0)
T
8

Start your activity with request code :

StartActivityForResult(intent,1234);

And you can close it from any other activity like this :

finishActivity(1234);
Tricorn answered 12/7, 2018 at 14:23 Comment(2)
In what language??Sartorial
'startActivityForResult(Intent!, Int): Unit' is deprecated. Deprecated in JavaAllpowerful
Y
5

See my answer to Stack Overflow question Finish All previous activities.

What you need is to add the Intent.FLAG_CLEAR_TOP. This flag makes sure that all activities above the targeted activity in the stack are finished and that one is shown.

Another thing that you need is the SINGLE_TOP flag. With this one you prevent Android from creating a new activity if there is one already created in the stack.

Just be wary that if the activity was already created, the intent with these flags will be delivered in the method called onNewIntent(intent) (you need to overload it to handle it) in the target activity.

Then in onNewIntent you have a method called restart or something that will call finish() and launch a new intent toward itself, or have a repopulate() method that will set the new data. I prefer the second approach, it is less expensive and you can always extract the onCreate logic into a separate method that you can call for populate.

Yester answered 30/4, 2012 at 6:12 Comment(0)
T
5

I've just applied Nepster's solution and works like a charm. There is a minor modification to run it from a Fragment.

To your Fragment

// sending intent to onNewIntent() of MainActivity
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.putExtra("transparent_nav_changed", true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

And to your OnNewIntent() of the Activity you would like to restart.

// recreate activity when transparent_nav was just changed
if (getIntent().getBooleanExtra("transparent_nav_changed", false)) {
    finish(); // finish and create a new Instance
    Intent restarter = new Intent(MainActivity.this, MainActivity.class);
    startActivity(restarter);
}
Tallahassee answered 29/3, 2015 at 12:1 Comment(0)
D
2

I think i have the easiest approach... on pressing new in B..

Intent intent = new Intent(B.this, A.class);
intent.putExtra("NewClicked", true);
 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

and in A get it

  if (getIntent().getBooleanExtra("NewClicked", false)) {
        finish();// finish yourself and make a create a new Instance of yours.
      Intent intent = new Intent(A.this,A.class);
      startActivity(intent);
    }
Doubleedged answered 26/6, 2014 at 14:45 Comment(0)
E
2

I know this is an old question, a few of these methods didn't work for me so for anyone looking in the future or having my troubles this worked for me

I overrode onPause and called finish() inside that method.

Epode answered 9/9, 2017 at 3:34 Comment(0)
S
-3

First call startactivity() then use finish()

Sinewy answered 29/1, 2018 at 15:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.