11

In my app I need to ask the user a quick input.

I need to get a result from this Flash-Activity and then get back to the previous one.

I've read about the StartActivityForResult() method, but I'm not yet sure how to use it properly, any examples?

EDIT:

I've tried to pass the Player object via intent (as the result) using the method I used in all the app applied to this method of the StartActivityForResult():

In my second Activity (the one where I need to get the result from):

Intent intent = new Intent();
Player playerKilled = players.get(position);

Bundle bundle = new Bundle();
bundle.putSerializable("PLAYER_KILLED", (Serializable) playerKilled);
intent.putExtras(bundle);

setResult(Activity.RESULT_OK, intent);
finish();

My Main Activity where I need to take the result to:

if (resultCode == Activity.RESULT_OK) {

    Intent intent = this.getIntent();
    Bundle bundle = intent.getExtras();
    playerKilled = (Player)bundle.getSerializable("PLAYER_KILLED");

    Toast.makeText(this, playerKilled.getName() + "the " + playerKilled.getCardName() + " has died, and he/she had the ID: " + playerKilled.getId(), Toast.LENGTH_SHORT).show();
Morgoth
  • 4,935
  • 8
  • 40
  • 66
FET
  • 942
  • 4
  • 13
  • 35
  • 2
    Is there a problem here or are you asking for a design opinion on your own app? If the later, that's off topic for StackOverflow – OneCricketeer Jun 11 '16 at 21:20
  • 1
    Consider moving this question to the [code review](http://codereview.stackexchange.com/) site. – 0x6C38 Jun 11 '16 at 21:21
  • Nope, I'm asking how to make a sort of pop-up windows, I mean, an activity that dosen't make loose the focus on tha main activity (the ListView). The code is just to help you. If you need to take a closer look, not asking for a review. @MrD – FET Jun 11 '16 at 21:37
  • Yeah it's @cricket_007 How to make such.. "activity" – FET Jun 11 '16 at 21:37
  • @Snip3r_bow Might want to rephrase the question in that case – 0x6C38 Jun 11 '16 at 21:54
  • Is a dialog suitable? Or else you could launch an activity that looks like a dialog? – SQLiteNoob Jun 11 '16 at 22:19
  • Why not then simply create a simple dialog that you show within that same activity? – Eenvincible Jun 12 '16 at 21:20
  • Would that fit a ListView right? @Eenvincible – FET Jun 12 '16 at 21:24
  • @Snip3r_bow I'm not sure what you're asking exactly. Do you want the input to be from the dialog, because you mentioned that you don't want it to lose focus from the main activity? What do you mean by this - do you want to still be able to access the activity's `ListView` (as you mentioned) whilst you are asking for an input? – Farbod Salamat-Zadeh Jun 16 '16 at 10:21
  • I'm sorry, I still didn't know the StartActivityForResult() method when I first asked this question, now I know it my question is how to properly use it to start another Activity and get back a result from it (the name of a Player object inside our RecyclerView). I just need to know how to use this method, I know how to get what I want, but I don't know how to send it using this method @FarbodSalamat-Zadeh – FET Jun 16 '16 at 10:27
  • @Snip3r_bow So I assume you want the main activity to launch a second activity with the `RecyclerView` (from your previous question) and then when an item is clicked, it returns the result to the main activity. – Farbod Salamat-Zadeh Jun 16 '16 at 10:30
  • Right to the point ;) @FarbodSalamat-Zadeh – FET Jun 16 '16 at 10:42

3 Answers3

21

You can request user input in a number of ways, but if you want to use a new Activity, as you mentioned, we can use startActivityForResult() to launch a new activity and return the input from there.

Firstly, I would highly recommend reading through this Stack Overflow answer about how to use startActivityForResult(). I will explain how you can implement it for your specific use case.

So, you need to understand that startActivityForResult() has two parameters:

  • the Intent (which you use to pass data between activities)
  • a "request code" integer that identifies your request

It is good practice to use a constant for your request code that you can access in both of your activities. For example, in your main activity, you could add:

public static final int REQUEST_CODE = 1;

This would be accessible in both activities since it is public, and it would work for a request code since it is an int (integer).

In your main activity, you need an action (such as a button press) to start your second activity. Let's assume it is a button click that triggers this action:

Button button = (Button) findViewById(R.id.your_button);
button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        // actions that will happen when the button is pressed:

        Intent intent = new Intent(this, SecondActivity.class);
        startActivityForResult(intent, REQUEST_CODE);
    }
});

Basically, we are creating an Intent which specifies our current activity (this) and the second activity. We use the intent in the startActivityForResult() method along with the REQUEST_CODE we declared earlier.

Now, in our second activity, we need something to trigger the data being returned back. From the previous question you asked, I'm assuming you want data to be returned to the main activity when a RecyclerView item has been clicked. Here is part of my answer to that question modified to show how data will be sent back.

ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
    @Override
    public void onEntryClick(View view, int position) {
        Intent intent = new Intent();
        intent.putExtra("pos", position);
        setResult(Activity.RESULT_OK, intent);
        finish();
    }
});
recyclerView.setAdapter(clickAdapter);

The above will send back the position of the list item from the RecyclerView clicked.

Have a look at the Intent's putExtra() method. This is what passes data. You can see that I have passed a String "pos" and the variable for the item position in this method, but why:

intent.putExtra("key", object);

The putExtra method of Intents always use a String key and another object, such as your integer variable, position. The key will be used again when retrieving this object (as I will show you later).

We use Activity.RESULT_OK to say that we are passing a result, but you can use Activity.RESULT_CANCELED if you don't want to send back a result - this is explained in the answer link I mentioned at the beginning. Note that if you use Activity.RESULT_CANCELED, you would not need to use putExtra as there would be nothing to send back.

Finally, you need to add something into your main activity which will deal with receiving the results from your second activity:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == REQUEST_CODE) {

        if (resultCode == Activity.RESULT_OK) {
            int result = data.getIntExtra("pos");
            // do something with the result

        } else if (resultCode == Activity.RESULT_CANCELED) {
            // some stuff that will happen if there's no result
        }
    }
}

We use the onActivityResult method for this.

At the beginning of this method, we are checking to see if the requestCode is the same as the one we defined earlier (as a public constant, REQUEST_CODE).

If so, we continue and check to see what the resultCode of the result was. If data was sent back (Activity.RESULT_OK), we can retrieve it using getIntExtra() as the position was an integer (similarly, use getStringExtra() if you are returning a String). Then you can do something with the returned data. However, if data was not sent back (as we mentioned earlier with Activity.RESULT_CANCELED), you can do something else.

Hopefully this helps you with implementing your idea, but a Google search would've found the answer I mentioned above (here is the link again) which clearly explained how to use startActivityForResult(). Other answers for this question also explain it well, but perhaps you needed guidance on how to implement it in your use case (i.e. combined with your code from the previous question you had), which is why I've provided the explanation above.

You can also read the Android documentation on Getting a Result from an Activity as well as Android documentation for the [startActivityForResult() method](https://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int)) and Intents.

Community
  • 1
  • 1
Farbod Salamat-Zadeh
  • 19,687
  • 20
  • 75
  • 125
  • Hey, I'd like to pass as value the Player object, but my method (which I've updated my question with) doesn't seem to be working, any ideas why? – FET Jun 16 '16 at 14:10
  • @Snip3r_bow To pass objects, I would make your `Player` object implement `Parcelable` instead of using `Serializable`. There's a good answer explaining how to do that [here](http://stackoverflow.com/a/7181792/4230345). After modifying your `Player` object in this way, I would use `putParcelable("PLAYER_KILLED", playerKilled)` - you should not have to cast it to anything here. Similarly, in your main activity, you would use `getParcelable` instead of `getSerializable`. There is the [official documentation for this](https://developer.android.com/reference/android/os/Parcelable.html) as well. – Farbod Salamat-Zadeh Jun 16 '16 at 17:16
  • Cheers, I've temporary solved this passing the position and gettin' the Player in the `MainActivity`, but will surely try to implement the `Parcelable` in the future updates as I've heard it's better than `Serializable` in some cases – FET Jun 16 '16 at 18:21
  • Hey man, may I ask you to have a look at [this](http://stackoverflow.com/questions/37924789/passing-a-reference-in-java) question? I think you're one of the only ones who can really understand and help there – FET Jun 20 '16 at 20:22
  • @Snip3r_bow I'll check it out tomorrow - is it your question? – Farbod Salamat-Zadeh Jun 20 '16 at 21:16
  • Yeah, I'm sorry for that – FET Jun 20 '16 at 21:26
  • Found anything? Any ideas? – FET Jun 21 '16 at 22:12
2

If I understand your question correctly, I am confident you want this solution:

startActivityForResult(intent, REQUEST_CODE);

simply create your activity with a list of items (recyclerview?) then to start it in order to get the results back, you basically create your intent and call the above method.

Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent, SOME_UNIQUE_CODE);

Now, after you are in the list activity, simply do the following when a user has selected the item:

intent = new Intent();
intent.putExtra("id", "Some Value Here to return");
setResult(RESULT_OK, intent);
finish();

So, immediately a user clicks an item from the list, you use this code to pass back your value and close this list activity.

Lastly, to actually receive this value passed, you simply Override onActivityResult()

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
    if (requestCode == REQUEST_CODE){
        if (resultCode == RESULT_OK){

            id = data.getExtras().getString("id");
        }
    }
}

This is all you need! I would say creating an activity is totally fine even though it does just one thing - displays a list of items! I hope this helps you! Good luck and happy coding!

Eenvincible
  • 5,641
  • 2
  • 27
  • 46
0

What you can do is pop up an activity that looks like a dialog.

In the manifest, where you declare the activity, include a dialog theme:

<activity
    android:name="com.myapp.DialogActivity"
    android:theme="@android:style/Theme.Holo.Light.Dialog"
    ...
</activity>

Then call the activity the normal way you would, with a result if you like:

Intent i = new Intent(this, DialogActivity.class);
startActivityForResult(i, REQUEST_CODE);
Farbod Salamat-Zadeh
  • 19,687
  • 20
  • 75
  • 125
SQLiteNoob
  • 2,958
  • 3
  • 29
  • 44
  • Mh, and would this dialog themed activity make me go back to the previous activity after closed? – FET Jun 12 '16 at 19:30
  • I think it's right what I was asking for, reading the Official tutorial of the startActivityForResult method, will let you know if this worked – FET Jun 12 '16 at 19:32
  • Yeah, it would bring you back to the previous activity that called it - I use this myself instead of the dialog classes when I need something a little more powerful. – SQLiteNoob Jun 12 '16 at 19:42
  • Mh, I see on the docs I have to use the CursorLoader, is it right? Take a [look](https://developer.android.com/training/basics/intents/result.html) – FET Jun 12 '16 at 19:46
  • It's in the last part of code (there are 3 in total) – FET Jun 12 '16 at 19:47
  • That example is just how to root through the contact list on your phone. It depends what data you're trying to persist - I'm a fan of `SharedPreferences` for a lot of things. But you return to the activity in `onActivityResult` where you can process whatever you passed it from the dialog activity in another `intent`. – SQLiteNoob Jun 12 '16 at 19:51
  • Alright, I think I got ya, I'll try now to apply that to my app, I'll let you know here if I was successful or not :) – FET Jun 12 '16 at 20:07
  • Hey, how may I edit the layout? I mean, the one of the dialog – FET Jun 12 '16 at 20:29
  • Like to make display a `ListView` – FET Jun 12 '16 at 20:30
  • That's getting away from the scope of the question, but it's an activity - so you'd set it up in the normal fashion as any other ListView. – SQLiteNoob Jun 12 '16 at 20:32
  • Mmmm you're right, as it doesn't work shall I make a question on this? – FET Jun 12 '16 at 21:07
  • Sure, I'll check it out. But you should be able to customize the activity class as needed. – SQLiteNoob Jun 12 '16 at 22:40
  • I'm not crazy, check out here: http://stackoverflow.com/questions/7631007/is-it-possible-to-have-listview-inside-a-dialog – SQLiteNoob Jun 12 '16 at 22:41
  • ie create an xml that includes a listview element, and put the xml in your setContentView in the DialogActivity's onCreate – SQLiteNoob Jun 12 '16 at 22:44
  • But what's the main difference between creating a Dialog with a ListView inside and a ListAvticity? – FET Jun 13 '16 at 09:43