Using startActivityForResult, how to get requestCode in child activity?
Asked Answered
D

4

91

I have four activities, say A, B, C and D. My situation is A will start the activity B by startActivityForResult.

startActivityForResult(new Intent(this,B.class),ONE);

In another situation I will start activity B with a different request code, like:

 startActivityForResult(new Intent(this,B.class),TWO);

In B, I need to call C or D depending on requestCode. I.e if ONE need to start C else D.
So I need to know how to check the requestCode in the child Activity (B here).
In other words, I want to get the request code that Activity B was started with.

Durfee answered 24/2, 2011 at 11:53 Comment(0)
A
145

You can pass request code by put extra.

intent.putExtra("requestCode", requestCode);   

Or if you have used startActivityForResult many times, then better than editing each, you can override the startActivityForResult in your Activity, add you code there like this

@Override
    public void startActivityForResult(Intent intent, int requestCode) {
        intent.putExtra("requestCode", requestCode);
        super.startActivityForResult(intent, requestCode);
    }

So there is no need to edit all your startActivityForResult
Hope it helped you

Algernon answered 24/2, 2011 at 12:12 Comment(4)
Is there really no way for a child activity to get its request code?Inearth
Till now to my best Knowledge, I think no other way.Algernon
Was wondering the same thing - this is one of those things in the Android APIs that doesn't make any logical sense.Clamant
startActivityForResult can be used to start activities in other apps, requestCode is your app's private matter. In this light it makes sense Intent has no such method and the right approach is to setAction advising exactly what you want the Activity to do.Benighted
D
29

The request code is not passed to the started activity automatically because it doesn't (and shouldn't) need to know this value. It only needs to know what to do and not where it was started from.

Starting an activity is really just another form of calling a method. When you call a method, you receive the result synchronously (right there where you made the call). In this case you are only passing in the information that method needs to do its work. You are not telling it where you called it from.

Starting an activity is the asynchronous analog of calling a method, in which case you receive the result in the special method onActivityResult(). In this method, you need to know what to do with the result you just received and you have the request code for this.

To make it a bit clearer why it isn't a good idea to pass the request code as a parameter, consider the example activity which is showing a product you can buy. On this activity there are two buttons labeled "Buy" and "Login" (as you are currently not logged in). Pressing "Login" will start an activity named "Login" which will try to log in the user using the provided information. Pressing "Buy" will first start the very same "Login" activity and if the login was successful, start the buy activity.

Now, the "Login" button uses request code 1 to start the login activity, but the "Buy" button can't use the same request code as it will have to do something different if the login is successful. So, the "Buy" button uses request code 2.

In the "Login" activity you might receive two different request codes depending on where it was called from, but you will need to do the very same procedure.

So, if you pass in the request code as a parameter, you will end up with code that needs to do the same stuff for a couple of different request codes, like:

if (requestCode == LOGIN || requestCode == BUY) {
    // ...
} else ...

You will also end up with storing the request code constants in a central location e.g. a class named RequestCodes.

In short, the request code should only be used to decide what to do with the received result. This way you will end up with a more modular, easier to maintain and easier to extend code.

Dynamometry answered 4/10, 2011 at 12:59 Comment(6)
What if it's a "manager" of sort and you want a request code to come in to "save" a certain value (value saved in extras). Another request code that would "retrive" a value (and return in extras) but within this activity they can also overall manage the saved values like renaming, editing, deleting, etc. What are your thoughts on something like that? I think it would prevent duplicating code/activities to do the same actions.Hiller
@J.Romero Don't do that, it will just complicate things. Just put that functionality in a (utility/singleton) class. You might also want to look at Handler and ServiceDynamometry
Szabolcs The child activity even if it "doesn't need to know this value" may need to pass the value on to the next activity in a chain. Ironically, we need to write more redundant code for this. For something that we don't need to know as much as we get more lecture to read about what what we shouldn't do.Aw
I don't see how this illustrates why a child activity should be denied access to the request code. I'm not even sure why accessing the request code would be necessary in your particular example considering the buy now and login calls are to two separate activities anyway.Pineapple
Not to revive a dead post, but I agree with Josh. What If you have a case where you have an ADD/Edit screen. You first want to add an item, but then what if you want to edit it later? you'd use the same activity, but when editing, you would change controls to the values you feed in. You don't want to create two activities for the same thing, so in the end you still would have to pass an extra in, in my case i pass in an int value equal to 100 for add, or 200 for edit, then work after that, since I can't pull the request code.Cress
@EvanR. perhaps a better architecture would be to subclass the "master" item activity into separate add/edit activities. So there's minimal reuse of code, but each activity can be invoked independently.Karalee
T
13

I ended up using custom Intent action to pass this kind of information to the launching Activity.

protected static final String ACTION_DO_C = "do_c";
protected static final String ACTION_DO_D = "do_d";

Then you'd go like:

final Intent intent = new Intent(this,B.class)
intent.setAction(ACTION_DO_C);
startActivityForResult(intent,ONE);

And in Activity B you get the action easily:

getIntent().getAction();
Topeka answered 30/6, 2015 at 11:5 Comment(1)
works like a charm, best answer really. Thanks.Ankus
L
0

You can use getCallingActivity() to get the activity that started current activity and that will receive the result value with response code at the end.

Loppy answered 21/3, 2019 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.