This question already has answers here:
How do I pass data between Activities in Android application?
(53 answers)
How to manage startActivityForResult on Android
(14 answers)
Closed 5 years ago.
I am trying to send and receive data between two different activities. I have seen some other questions asked on this site but no question has dealt with preserving the state of the first class.
For example if I want to send an integer X to class B from class A then to do some operations on integer X and then send it back to class A, how does one go about doing this?
Is it as simple as the following code?
in Class A
Intent i = new Intent(this, ActivityB.class);
i.putExtra("Value1", 1);
startActivity(i);
and to receive the response from Class B:
Bundle extras = getIntent().getExtras();
int value1 = extras.getint("Value1",0);
in Class B
Bundle extras = getIntent().getExtras();
int value1 = extras.getint("Value1",0);
//Do some operations on value1 such as maybe adding or subtracting
Intent i = new Intent(this, ActivityA.class);
i.putExtra("Value1", 1);
startActivity(i);
This does not seem correct as I simply want to switch back to Activity A and receive the data from Activity B once the action is completed (perhaps a button in Activity B commences operations on the received data and then sends it back to Activity A?)
In First activity :
Intent i = new Intent(this, ActivityB.class);
i.putExtra("Value1", "1");
startActivityForResult(i, 100);
Receive data like :
Intent receivedIntent = getIntent();
if(receiveIntent!=null){
String value1 = receiveIntent.getStringExtra("Value1");
}
After some operations In second activity:
Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();
Handle result in FirstActivity :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
}
}
}
startActivityForResult() and onActivityResult() is your solution.
In your ActivityA. Use startActivityForResult() -
Intent i = new Intent(this, ActivityB.class);
i.putExtra("Value1", 1);
startActivityForResult(i, requestCodeForOperation);
And on your ActivityB, get your data sent from ActivityA. Like -
int value1 = getIntent().getExtras().getInt("Value1", 0);
Do your operation and use setResult() for adding you operation result and finish(). like-
Intent returnIntent = new Intent();
returnIntent.putExtra("result",result);
setResult(Activity.RESULT_OK,returnIntent);
finish();
And of course you need to implement onActivityResult() on ActivityA to get returned data from ActivityB. Like -
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == requestCodeForOperation) {
if(resultCode == Activity.RESULT_OK){
String result=data.getIntExtra("result", 0);
}
}
}
Related
I have two activities that should pass data back and forth to each other using intents. I'm not sure where to place some of the puts and gets though.
For Activity1 (MainActivity), I have a button, and on press it creates an intent, and then puts it to Activity2, then starts it using startActivity(intent).
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("test", testClass);
startActivity(intent);
});
Then in Activity2, I get that information in the onCreate() function using getIntent.
Now what I want to do is have a button in Activity2 that will pass data to Activity1, but won't necessarily "start/show" the activity.
So I'm wondering how this can be done.
My idea is to have the following similar to before:
Activity2:
btn.setOnClickListener((v) -> {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("info", info);
});
But I'm confused about two things
Can I do this without starting the activity right away
Where would I do the getIntent call in MainActivity to retrieve this data
You can use startActivityForResult to start Activity2 and receive a result back to Activity1
Activity 1
int LAUNCH_ACTIVITY_TWO = 1;
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
//onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
}
}
}
Activity 2
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
Full Activity 1 code:
public class MainActivity extends AppCompatActivity {
public static int LAUNCH_ACTIVITY_TWO = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent i = new Intent(this, Activity2.class);
i.putExtra("test", testClass);
startActivityForResult(i, LAUNCH_ACTIVITY_TWO);
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LAUNCH_ACTIVITY_TWO) {
if(resultCode == Activity.RESULT_OK){
String result= data.getStringExtra("result");
}
}
}
}
Full Activity 2 code:
public class Activity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(getIntent().getExtras() != null) {
// Get intent extras from Activity 1
}
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener((v) -> {
Intent returnIntent = new Intent();
returnIntent.putExtra("result", result);
setResult(Activity.RESULT_OK, returnIntent);
finish();
});
}
}
You can for example create a list in activity2 to which you add the data you want to pass to activity1. Before starting activity1 you get the values out of your array and add them as extras to the input.
You can have the data added to a JSONObject and use a serializer so you don't have to add your items all by yourself.
If you want to pass your data to activity1 without starting it,so activity1 processes the data, that is not possible. Activity doesnt execute anything while you are in activity2, for such cases you use fragments.
If you use fragments you can put all data in a viewmodel which is bound to the activity instead of each fragment.
There are several ways you can achieve this pending on what type of data you're looking at passing.
If it's an entire class object then make the class parcable. You can copy and paste the class in this website http://www.parcelabler.com/ and it auto formats it for you. All you do is pass it as an intent extra.
If you're looking at data that needs an action performed on it and then passed to another activity I would suggest using and intent service. You can perform certain actions pending the intents received in the service.
If you're looking at performing certain actions only after XYZ has occurred in your application then used shared preferences. These can be accessed anywhere quite easily.
Lastly, if you're using bulk data consistently that needs to remain persistent, use a local database storage and just query when you need to.
You can use SharedPreferences or static variables/fields for that.
I am having a problem receiving the extras that are coming in with my intent from a different activity. When I run the code and use break points at the line where the object is actually being created I can see it being created using the debugger. I can see the object being put in the putExtra() function.
Upon arrival at the resulting activity though using the function getParceableExtra() always returns null upon receiving the intent.
//In the receving activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == 1){
if(resultCode == Activity.RESULT_OK){
Intent extras = getIntent();
if(extras != null){
Goals addToList = extras.getParcelableExtra(GOAL_PASSING);
if(addToList != null)
mGoal.add(addToList);
}
}
}
}
//In the sending activity
incrementMGoal = (findViewById(R.id.create_goal_button));
incrementMGoal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent returnIntent = new Intent();
Goals newGoal = new Goals(GT,GD,GDueDate);
returnIntent.putExtra(MainActivity.GOAL_PASSING,newGoal);
setResult(Activity.RESULT_OK,returnIntent);
finish();
}
});
I expect when I create the intent to pass putExtra and then receive it to be put in a array. I am just receiving null however.
The Problem is that your code takes the wrong intent and not of the onActivityResult parameter data
Goals addToList = data.getParcelableExtra(GOAL_PASSING);
so instead you should do this
Goals addToList = data.getParcelableExtra(GOAL_PASSING);
I have 3 Activities. Intent is passed from Activity 1 to Activity 2 with some data which is to be used for DB transactions. From Activity 2 data and Intent are passed to Activity 3.
Now, i want to transfer from Activity 3 to Activity 2 but as activity 2 gets intent from Activity 1 , it returns some error which results in null exceptions :/
So , i want to refresh activity 2 on returning from Activity 3 , but without intent or proper use of intent which does not affect data
Start Activity2 from Acivity1 as:
Intent i = new Intent(this, Activity2.class);
startActivityForResult(i, 1);
in Activity2 use setResult for sending data back :
Intent intent = new Intent();
intent.putExtra("edittextvalue","value_here")
setResult(RESULT_OK, intent);
finish();
and in First Activity receive data as onActivityResult:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK){
String stredittext=data.getStringExtra("edittextvalue");
}
}
}
OR
You can use this
In Activity2,
#Override
public void onBackPressed() {
String data = mEditText.getText();
Intent intent = new Intent();
intent.putExtra("MyData", data);
setResult(resultcode, intent);
}
In Activity1,
onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
String myStr=data.getStringExtra("MyData");
mTextView.setText(myStr);
}
}
}
OR
you can use SharedPreferences also for Sharing data Between Activities
You can use interfaces to achieve this. Example: in your Activity3, create an interface:
interface Communicator {
void receiveData(Object toSend);
}
Then you implement your Activity2 as follows:
public class Activity2 extends Activity implements Activity3.Communicator, Serializable {
//You'll have to implement the method
public void receiveData(Object toSend) {
//do what you have to do with your object once it's been sent back.
}
}
In order to use this pattern, you'll have to use an intent to start Activity3 like you did. I used Serializable because you want to pass an instance of the Activity through the Intent:
Intent intent = new Intent(this, Activity3.class);
intent.putExtra("activity2", this);
startActivity(intent);
You retrieve the Activity2 object in Activity3 in its onCreate method:
public class Activity3 extends Activity {
private Communicator mActivity2; //your activity
private Object mData; //Whatever object you want to send
public void onCreate(Bundle bundle) {
//...
Intent intent = getIntent();
Serializable object = intent.getSerializableExtra("activity2");
if (object != null && object instanceof Communicator) {
//make sure the object is not null and implements the Communicator
mActivity2 = (Communicator) object;
}
}
}
Once you are done in your Activity3 (once it is closed), you implement a method like onBackPressed or onDestroy as follows:
#Override
public void onDestroy() { //better if the back button is not pressed
super.onDestroy();
if (mActivity2 != null) { //check if is not null
mActivity2.receiveData(mData);
}
}
And your Activity should be updated without using intents.
By the way, using Fragments using this pattern is MUCH better than Activities. You should use fragments instead.
I have two Activities: ActivityA and ActivityB.
I start ActivityB with startActivityForResult:
Intent lIntent = new Intent(ActivityA.this, ActivityB.class);
startActivityForResult(lIntent, 1);
I have this code to go back from ActivityB to ActivityA(ActivityB can call itselfs many time):
Intent intent = new Intent(ActivityB.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("files",
mChecked.toArray(new String[mChecked.size()]));
startActivity(intent);
//setResult(Activity.RESULT_OK, intent);
That code runs fine without setResult. My problem is I have to set RESULT_OK to deal correctly with the result in ActivityA:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1){
if (resultCode == Activity.RESULT_OK){ <-- always 0 and not -1
System.out.println("OK");
}
}
}
if I comment in setResult in ActivityB, onActivityResult is never called.
If I use startActivity, onActivityResult is called but the resultCode is not set.
How can I set the result code in my case?
UPDATE
Intent intent = new Intent(FileChooserActivity.this,FtpContentListView.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("files", mChecked.toArray(new String[mChecked.size()]));
setResult(Activity.RESULT_OK, intent);
startActivity(intent);
with that code onActivityResult is called but the resultCode is 0 and not -1(RESULT_OK).
Thanks a lot for your help
Stefan
I believe what you're after is to first start Activity B for result (as you are currently), then subsequently starting new instances of Activity B using the Intent.FLAG_ACTIVITY_FORWARD_RESULT. Note however, that you would need to finish previous instances of Activity B whenever you create new ones (as described in this gist https://gist.github.com/mcelotti/cc1fc8b8bc1224c2f145).
Alternatively, you could simply start all instances of Activity B for result and pass down the result until Activity A was reached:
#Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
setResult(resultCode);
finish();
}
You need to make a change in Activity-B :
Bundle b = new Bundle();
b.putStringArray("files",
mChecked.toArray(new String[mChecked.size()]));
Intent intent = new Intent(ActivityB.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtras(b);
setResult(RESULT_OK, intent);
finish();
Hope this works.
I have an object called Contact which contains an arraylist of type Transactions.
I pass the selected contact (from a listview in activity1) to activity2 using intent and startActivityForResult.
In the second activity I create a new Transaction object and add it to the passed Contact's arraylist of transactions, return it using setResult and retrieve it using onActivityResult
My problem is that the original Contact object doesn't get the new Transaction.
Sending intent:
Intent intent = new Intent(this, AddTransactionActivity.class);
intent.putExtra("contact", selectedContact);
startActivityForResult(intent, 1);
recieving intent:
Bundle b = getIntent().getExtras();
if(b != null) {
recievedContact = (Contact)b.getParcelable("contact");
}
Sending back result:
recievedContact.addTransaction(transaction);
Intent intent = new Intent(this, Contacts_activity.class);
intent.putExtra("contact", recievedContact);
setResult(Activity.RESULT_OK, intent);
finish();
startActivity(intent);
Retrieving result:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1) {
if(resultCode == Activity.RESULT_OK) {
Bundle b = data.getExtras();
if(b != null) {
selectedContact = (Contact)b.getParcelable("contact");
}
} else if (resultCode == 0) {
}
}
}
edit: I put a Log.v("result test", "success"); in onActivityResult(), it doesnt show in logcat so it seems my onActivityResult method is never called.