332

I have two activities: main activity and child activity.
When I press a button in the main activity, the child activity is launched.

Now I want to send some data back to the main screen. I used the Bundle class, but it is not working. It throws some runtime exceptions.

Is there any solution for this?

Adinia
  • 3,722
  • 5
  • 40
  • 58
Rajapandian
  • 7,059
  • 11
  • 37
  • 27
  • Possible duplicate of [How do I pass data between Activities in Android application?](https://stackoverflow.com/questions/2091465/how-do-i-pass-data-between-activities-in-android-application) – NoDataDumpNoContribution Apr 25 '19 at 15:52
  • One more trick define an ArrayList in your main activity and make it static so you can access it in second activity then add data in itthat you want to send to main activity then you access it in main activity – Abhi Aug 28 '19 at 20:40
  • Abhishek Yadav, what if your main activity is going to destroy(onDestroy() callback). I think it's not very good advice. – Leontsev Anton Jan 18 '20 at 14:44

13 Answers13

524

There are a couple of ways to achieve what you want, depending on the circumstances.

The most common scenario (which is what yours sounds like) is when a child Activity is used to get user input - such as choosing a contact from a list or entering data in a dialog box. In this case, you should use startActivityForResult to launch your child Activity.

This provides a pipeline for sending data back to the main Activity using setResult. The setResult method takes an int result value and an Intent that is passed back to the calling Activity.

Intent resultIntent = new Intent();
// TODO Add extras or a data URI to this intent as appropriate.
resultIntent.putExtra("some_key", "String data"); 
setResult(Activity.RESULT_OK, resultIntent);
finish();

To access the returned data in the calling Activity override onActivityResult. The requestCode corresponds to the integer passed in the startActivityForResult call, while the resultCode and data Intent are returned from the child Activity.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  switch(requestCode) {
    case (MY_CHILD_ACTIVITY) : {
      if (resultCode == Activity.RESULT_OK) {
        // TODO Extract the data returned from the child Activity.
        String returnValue = data.getStringExtra("some_key");
      }
      break;
    } 
  }
}
Ramesh R
  • 7,009
  • 4
  • 25
  • 38
Reto Meier
  • 96,655
  • 18
  • 100
  • 72
  • 5
    for completeness one should mention what is the best place to place the call to finish()? It maybe clear to experts, but for the beginners would be good to know without referencing additional sources. – Califf Jul 01 '15 at 19:36
  • 3
    @jelmoodjasser It took me a bit to figure out, but basically when you start the new activity with Intent you need to use the `startActivityForResult` function instead of just `startActivity`. An example might be `startActivityForResult(myIntent, 2);` where 2 is the result code, which can take the place of `MY_CHILD_ACTIVITY` in the switch statement above. – Spotlight Aug 18 '16 at 15:01
  • when second activity finished and returns to first activity then how to set requestCode into second activity before finish it.... for use it to onActivityResult in FirstActivity – Ahamadullah Saikat Oct 09 '17 at 10:01
  • Is Intent mandatory? If I don't have anything to send back do I need the empty intent to sent back? – Bagus Aji Santoso Jan 07 '20 at 15:55
  • @BagusAjiSantoso intent is optional, only needed if you have anything to send back. – Narendra Singh Apr 17 '20 at 15:14
  • How about the case when you have a chain of activities? For example you need to first request sdcard access via `Intent.ACTION_OPEN_DOCUMENT` and then read/write files through another activity and then start yet another activity, all while maintaining some kind of state from the original activity? – ccpizza Apr 17 '20 at 19:11
  • This approach is deprecated. See here: https://stackoverflow.com/questions/62671106/onactivityresult-method-is-deprecated-what-is-the-alternative – Nicolai Weitkemper Jul 04 '23 at 18:18
195

Activity 1 uses startActivityForResult:

startActivityForResult(ActivityTwo, ActivityTwoRequestCode);

Activity 2 is launched and you can perform the operation, to close the Activity do this:

Intent output = new Intent();
output.putExtra(ActivityOne.Number1Code, num1);
output.putExtra(ActivityOne.Number2Code, num2);
setResult(RESULT_OK, output);
finish();

Activity 1 - returning from the previous activity will call onActivityResult:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == ActivityTwoRequestCode && resultCode == RESULT_OK && data != null) {
        num1 = data.getIntExtra(Number1Code);
        num2 = data.getIntExtra(Number2Code);
    }
}

UPDATE: Answer to Seenu69's comment, In activity two,

int result = Integer.parse(EditText1.getText().toString()) 
           + Integer.parse(EditText2.getText().toString());
output.putExtra(ActivityOne.KEY_RESULT, result);

Then in activity one,

int result = data.getExtra(KEY_RESULT);
evandrix
  • 6,041
  • 4
  • 27
  • 38
jimmithy
  • 6,360
  • 2
  • 31
  • 29
  • Hi there I appreciate u for answering my question.This code is not enough for me. I want addition to be performed in the second activity itself and the result should be returned to the MainActivity through onActivityResult method. For instance there is only button in the Main Activity which takes u to second activity on clicking it, there two numbers are entered through the editText widget, addition logic is performed in the second activity itselfand finally the result is returned to MainActivity. Got it? – Seenu69 Nov 13 '12 at 15:01
  • 2
    In that case in the second activity, you would perform the calculation and store the result in the intent with putExtra(). I've edited my answer above – jimmithy Nov 13 '12 at 15:23
81

Sending Data Back

It helps me to see things in context. Here is a complete simple project for sending data back. Rather than providing the xml layout files, here is an image.

enter image description here

Main Activity

  • Start the Second Activity with startActivityForResult, providing it an arbitrary result code.
  • Override onActivityResult. This is called when the Second Activity finishes. You can make sure that it is actually the Second Activity by checking the request code. (This is useful when you are starting multiple different activities from the same main activity.)
  • Extract the data you got from the return Intent. The data is extracted using a key-value pair.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private static final int SECOND_ACTIVITY_REQUEST_CODE = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // "Go to Second Activity" button click
    public void onButtonClick(View view) {

        // Start the SecondActivity
        Intent intent = new Intent(this, SecondActivity.class);
        startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE);
    }

    // This method is called when the second activity finishes
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // Check that it is the SecondActivity with an OK result
        if (requestCode == SECOND_ACTIVITY_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {

                // Get String data from Intent
                String returnString = data.getStringExtra("keyName");

                // Set text view with string
                TextView textView = (TextView) findViewById(R.id.textView);
                textView.setText(returnString);
            }
        }
    }
}

Second Activity

  • Put the data that you want to send back to the previous activity into an Intent. The data is stored in the Intent using a key-value pair.
  • Set the result to RESULT_OK and add the intent holding your data.
  • Call finish() to close the Second Activity.

SecondActivity.java

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

    // "Send text back" button click
    public void onButtonClick(View view) {

        // Get the text from the EditText
        EditText editText = (EditText) findViewById(R.id.editText);
        String stringToPassBack = editText.getText().toString();

        // Put the String to pass back into an Intent and close this activity
        Intent intent = new Intent();
        intent.putExtra("keyName", stringToPassBack);
        setResult(RESULT_OK, intent);
        finish();
    }
}

Other notes

  • If you are in a Fragment it won't know the meaning of RESULT_OK. Just use the full name: Activity.RESULT_OK.

See also

GabrielBB
  • 2,479
  • 1
  • 35
  • 49
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
45

FirstActivity uses startActivityForResult:

Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent, int requestCode); // suppose requestCode == 2

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 2)
    {
        String message=data.getStringExtra("MESSAGE");
    }
}

On SecondActivity call setResult() onClick events or onBackPressed()

Intent intent=new Intent();
intent.putExtra("MESSAGE",message);
setResult(Activity.RESULT_OK, intent);
José Silva
  • 534
  • 6
  • 16
Vijay
  • 608
  • 7
  • 11
16

UPDATE Mar. 2021

As in Activity v1.2.0 and Fragment v1.3.0, the new Activity Result APIs have been introduced.

The Activity Result APIs provide components for registering for a result, launching the result, and handling the result once it is dispatched by the system.

So there is no need of using startActivityForResult and onActivityResult anymore.

In order to use the new API, you need to create an ActivityResultLauncher in your origin Activity, specifying the callback that will be run when the destination Activity finishes and returns the desired data:

private val intentLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->

        if (result.resultCode == Activity.RESULT_OK) {
            result.data?.getStringExtra("key1")
            result.data?.getStringExtra("key2")
            result.data?.getStringExtra("key3")
        }
    }

and then, launching your intent whenever you need to:

intentLauncher.launch(Intent(this, YourActivity::class.java))

And to return data from the destination Activity, you just have to add an intent with the values to return to the setResult() method:

val data = Intent()
data.putExtra("key1", "value1")
data.putExtra("key2", "value2")
data.putExtra("key3", "value3")

setResult(Activity.RESULT_OK, data)
finish()

For any additional information, please refer to Android Documentation

Mike Grimm
  • 941
  • 11
  • 17
15

Call the child activity Intent using the startActivityForResult() method call

There is an example of this here: http://developer.android.com/training/notepad/notepad-ex2.html

and in the "Returning a Result from a Screen" of this: http://developer.android.com/guide/faq/commontasks.html#opennewscreen

Intrications
  • 16,782
  • 9
  • 50
  • 50
  • Yes, I concur with cbrulak, the link to the docs was way more helpful than the answer. – george_h Feb 26 '13 at 20:33
  • 1
    The links are showing some general things now. The content might be changed please update it or remove the answer for community – Manoranjan Sep 19 '19 at 13:06
8

I have created simple demo class for your better reference.

FirstActivity.java

 public class FirstActivity extends AppCompatActivity {

    private static final String TAG = FirstActivity.class.getSimpleName();
    private static final int REQUEST_CODE = 101;
    private Button btnMoveToNextScreen;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnMoveToNextScreen = (Button) findViewById(R.id.btnMoveToNext);
        btnMoveToNextScreen.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent mIntent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivityForResult(mIntent, REQUEST_CODE);
            }
        });
    }

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

        if(resultCode == RESULT_OK){
            if(requestCode == REQUEST_CODE && data !=null) {
                String strMessage = data.getStringExtra("keyName");
                Log.i(TAG, "onActivityResult: message >>" + strMessage);
            }
        }

    }
}

And here is SecondActivity.java

public class SecondActivity extends AppCompatActivity {

    private static final String TAG = SecondActivity.class.getSimpleName();
    private Button btnMoveToPrevious;
    private EditText editText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        editText = (EditText) findViewById(R.id.editText);

        btnMoveToPrevious = (Button) findViewById(R.id.btnMoveToPrevious);
        btnMoveToPrevious.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String message = editText.getEditableText().toString();

                Intent mIntent = new Intent();
                mIntent.putExtra("keyName", message);
                setResult(RESULT_OK, mIntent);
                finish();

            }
        });

    }
}
aminography
  • 21,986
  • 13
  • 70
  • 74
Kuls
  • 2,047
  • 21
  • 39
6

In first activity u can send intent using startActivityForResult() and then get result from second activity after it finished using setResult.

MainActivity.class

public class MainActivity extends AppCompatActivity {

    private static final int SECOND_ACTIVITY_RESULT_CODE = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    // "Go to Second Activity" button click
    public void onButtonClick(View view) {

        // Start the SecondActivity
        Intent intent = new Intent(this, SecondActivity.class);
        // send intent for result 
        startActivityForResult(intent, SECOND_ACTIVITY_RESULT_CODE);
    }

    // This method is called when the second activity finishes
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        // check that it is the SecondActivity with an OK result
        if (requestCode == SECOND_ACTIVITY_RESULT_CODE) {
            if (resultCode == RESULT_OK) {

                // get String data from Intent
                String returnString = data.getStringExtra("keyName");

                // set text view with string
                TextView textView = (TextView) findViewById(R.id.textView);
                textView.setText(returnString);
            }
        }
    }
}

SecondActivity.class

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

    // "Send text back" button click
    public void onButtonClick(View view) {

        // get the text from the EditText
        EditText editText = (EditText) findViewById(R.id.editText);
        String stringToPassBack = editText.getText().toString();

        // put the String to pass back into an Intent and close this activity
        Intent intent = new Intent();
        intent.putExtra("keyName", stringToPassBack);
        setResult(RESULT_OK, intent);
        finish();
    }
}
evandrix
  • 6,041
  • 4
  • 27
  • 38
Yogesh Adhe
  • 61
  • 1
  • 2
5

All these answers are explaining the scenario of your second activity needs to be finish after sending the data.

But in case if you don't want to finish the second activity and want to send the data back in to first then for that you can use BroadCastReceiver.

In Second Activity -

Intent intent = new Intent("data");
intent.putExtra("some_data", true);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

In First Activity-

private BroadcastReceiver tempReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // do some action
    }
};

Register the receiver in onCreate()-

 LocalBroadcastManager.getInstance(this).registerReceiver(tempReceiver,new IntentFilter("data"));

Unregister it in onDestroy()

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Shivam Yadav
  • 958
  • 11
  • 23
0

Another way of achieving the desired result which may be better depending on your situation is to create a listener interface.

By making the parent activity listen to an interface that get triggered by the child activity while passing the required data as a parameter can create a similar set of circumstance

Lenos
  • 11
  • 2
-1

There are some ways of doing this. 1. by using the startActivityForResult() which is very well explained in the above answers.

  1. by creating the static variables in your "Utils" class or any other class of your own. For example i want to pass studentId from ActivityB to ActivityA.First my ActivityA is calling the ActivityB. Then inside ActivityB set the studentId (which is a static field in Utils.class). Like this Utils.STUDENT_ID="1234"; then while comming back to the ActivityA use the studentId which is stored in Utils.STUDENT_ID.

  2. by creating a getter and setter method in your Application Class.

like this:

public class MyApplication extends Application {

    private static MyApplication instance = null;
    private String studentId="";

    public static MyApplication getInstance() {
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
    }

    public void setStudentId(String studentID){
        this.studentId=studentID;
    }

    public String getStudentId(){
        return this.studentId;
    }
}

so you are done . just set the data inside when u are in ActivityB and after comming back to ActivityA , get the data.

swetabh suman
  • 1,949
  • 2
  • 19
  • 24
-1

Just a small detail that I think is missing in above answers.

If your child activity can be opened from multiple parent activities then you can check if you need to do setResult or not, based on if your activity was opened by startActivity or startActivityForResult. You can achieve this by using getCallingActivity(). More info here.

Dhruv Jagetiya
  • 1,043
  • 12
  • 19
-4

Use sharedPreferences and save your data and access it from anywhere in the application

save date like this

SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(key, value);
    editor.commit();

And recieve data like this

SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
    String savedPref = sharedPreferences.getString(key, "");
    mOutputView.setText(savedPref);
Hybrid Developer
  • 2,320
  • 1
  • 34
  • 55
  • 6
    This would be more appropriate if the second activity was setting a permanent change/setting in the application. – elimirks Sep 26 '13 at 14:22
  • Will this work if I want to share data between 2 different android apps?One referred as library ? – joey rohan Mar 12 '14 at 17:25
  • 22
    This is SharedPreferences abuse. – Eran Goldin Aug 27 '14 at 22:32
  • 1
    Using this method for just passing data between two activities (OP's original question) is like abusing SharedPreferences. It is not meant for this and the system has to do too much work (writing xml on storage and reading it again) for a simple task like passing data between two activities. – Sudara Jul 22 '15 at 04:58