How to pass and manipulate objects between activities using intents - java

This is my first issue with the Android lifecycleand I feel somewhat helpless:
In Activity A there's onCreate. That's the spot where I create an ArrayList called playerNames and ArrayList called moves. Also there's some more stuff happening in oncreate. In A's onStart I create a flag so I know which Activity is running in case I'd like to close all at once. In onDestroy the flag is set back to null.
Eventually I make an intent to get to Activity B where I take the moves list along. Works fine.
Now I'd like to make an intent from B to get back to A. What happens in the lifecycle when I attempt that? Obviously onCreate of A is called and leads to a NullPointerException regrding the playerNames list.
I'd like to store this ArrayList while B is running and get it back when I come back to A. Which method is the right one (onResume? onRestart?) and how do I store it? Do I really need SharedPreferences?
Thanks in advance for your kind help

On Activity A:
-Create an Intent, specifying wich activity you want to start
-Put data on that intent to be received by activity B.
-Start Activity for a result.
-On onActivityResult() verify that you have data to receive and do what you want with it.
On Activity B:
-On the onCreate() receive the data from Activity A;
-Modify the data as you wish;
-Create a new Intent;
-Put the data in the Intent;
-Set the activity result and the intent data.
-Finish activity B
Below is a sample of the steps I describe, what it does is have activity A start an Activity B, and passing it an empty ArrayList. Then on Activity B, the arrayList is populated and sent back to Activity A where the contents of the arrayList, are displayed on screen.
Code:
Activity A:
private static final int REQUEST_LIST = 1;
ArrayList<String> myList;
TextView listText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listText = (TextView) findViewById(R.id.mylist_text);
myList = new ArrayList<String>();
Intent i = new Intent(MainActivity.this, ActivityB.class);
i.putExtra(ActivityB.EXTRA_ARRAY, myList);
startActivityForResult(i, REQUEST_LIST);
}
#Override
protected void
onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != Activity.RESULT_OK) return;
if (requestCode == REQUEST_LIST) {
myList = (ArrayList<String>) data.getSerializableExtra(ActivityB.EXTRA_ARRAY);
StringBuilder text = new StringBuilder();
for (int j = 0; j < myList.size(); j++) {
text.append(myList.get(j) + " ");
}
listText.setText(text.toString());
}
}
Activty B:
public static final String EXTRA_ARRAY = "com.example.androidtest.mainactivity.array";
ArrayList<String> myList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activityb_layout);
myList = (ArrayList<String>) getIntent().getSerializableExtra(EXTRA_ARRAY);
for (int i = 0; i < 10; i++) {
myList.add(String.valueOf(i));
}
Intent data = new Intent();
data.putExtra(EXTRA_ARRAY, myList);
setResult(Activity.RESULT_OK, data);
finish();
}
Attention: You cannot forget to declare your Activity B in the manifest File. Also pay attention on how the activities know what data to send and collect, through constants created in the classes, wich must be consistent, so avoid using literal strings, and use defined constants.

From Activity B you can come back to the previous A instance using:
Intent intent = new Intent(this, A.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
This will clear all current stack and go back to the A instance ( http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP ). As long as your Activity doesn't get destroyed, you'll have all data there.
Anyway, you should consider use Activity's save instance state capability ( http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState%28android.os.Bundle%29 ).

Related

Bundle loses all data between two Activities

I've got two different activities Menu and Exercise.
I need to pass some data from Menu to Exercise when I start the latter activity via the click of a button.
Here is the code in Menu activity:
Button b = (Button) findViewById(R.id.temp);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
Intent i = new Intent(context, ExerciseActivity.class);
Bundle b = new Bundle();
b.putString("colors","Blue");
b.putIntArray("workoutlist",new int[] {0,1});
i.putExtras(b);
//i.putExtra("workoutlist",MyApp.workoutList.get(0));
//i.putExtra("colors","Blue");
startActivity(i);
}
});
Using debugging tools I've checked that all the data are inside the bundle of the intent properly.
And here is the code that should retrieve data from the intent in Exercise Activity:
Intent in = getIntent();
Bundle b = in.getExtras();
String[] colorSets = (String[]) b.get("colors");
int[] l = (int[]) b.get("workoutlist");
The fact is when I get the bundle it is empty, and obviously I cannot proceed.
Moreover I already used almost the same code between to other activities and everything is working fine.
Why is this happening? Is it there something I'm missing which generates this error? Maybe some incompatibility between the two activities?
Thank you for your help!
you add String using putString() and get it using getString(). the same goes for other types.
Intent in = getIntent();
Bundle b = in.getExtras();
String colorSets = b.getString("colors");
int[] l = b.getIntArray("workoutlist");

How to refer to a randomly generated button's elements

I need to randomly generate a button and then grab elements from it from the activity that the button opens. Specifically the universal ID of a "character" that I have specified in PersistentData. (That whole class works fine, though. The problem is between this activity and the next.) The child activity has multiple activities that can call it. (There are several activities with lists made from different characters from a pool, and each list has these buttons that are shown below, which all point to the same activity that loads information from PersistentData based on the data that its supposed to pull from said button.) The following 1 block of code is in the onCreate method for this activity. (Automatically generated, I just added this in after I called the layouts from the XML file)
for (fID = 0; fID < PersistentData.fName.size(); fID++) {
if (PersistentData.fName.get(fID) != null) {
Button[] Btn = new Button[PersistentData.fName.size()];
Btn[fID].setHeight(200);
Btn[fID].setWidth(200);
Btn[fID].setTextSize(40);
Btn[fID].setText(PersistentData.fName.get(fID));
Btn[fID].setTag(fID);
Layout.addView(Btn[fID]);
Btn[fID].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int btnID = fID;
gotoActivity(v);
}
});
} else continue;
}
Here is gotoActivity(). (In the class, not onCreate)
public void gotoActivity(View view) {
Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);
intent.putExtra("btnClicked", /*IDK WHAT TO PUT RIGHT HERE*/);
}
I have put several things there, actually. Mostly, they have been various ways of declaring a variable on the creation of the button.
Here's the TargetActivity.class
public class Fighter extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fighter);
Intent intent = getIntent();
Bundle bundle =
intent.getExtras(); //line ***
**
TextView viewName = (TextView) findViewById(R.id.fighterName);
viewName.setText(PersistentData.fName.get(fID));
}
}
What should I put in the other class that I should get here**? (fID) is the thing that I'm trying to get. I have tried putting and getting fID using the methods as described in the Create an Activity page from Android and it continued to give me a NullPointerException at line *** (I split the line to be precise.)
Any help is appreciated. I would not be surprised if there is a better way to do this, requiring me to scrap all my work and restart. I would prefer not to, though lol. I will be checking this post periodically throughout the day, so if you have any questions or require more detail, just post or message me. Thank you beforehand.
I think the reason you got a NullPointerException because you started the activity before persing the extra.
In the gotoActiviy, make sure the extra(s) method are called before you start the activity. that is
public void gotoActivity(View view) {
Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("btnClicked", "Strings");
startActivity(intent);
}
As you can see, a string was the extra, you can put any variable type as the extra just make sure at the activity being called, the same variable type gets the extra.
as an example
String getValue = getIntent().getExtras().getString("btnClicked");
Int getValue = getIntent().getExtras().getInt("btnClicked");
/** If integer was the value activity extra */

How to save an int for another activity?

I have one activity where the user writes in an EditText a number, then I am supposed to convert it to a string and then to an int, but I want to save that value because I am going to use it for another activity, it will be the max number of times that a botton can be pressed but I don't know how to save it from the EditText in a activity to an int in another activity.
Here the EditText of the first activity:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="number"
android:ems="10"
android:id="#+id/texthome"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:hint="Ejemplo:15"
android:layout_weight="1"
android:textSize="20sp" />
Here the textview into int:
EditText conttext = (EditText) findViewById ( R.id.texthome );
String maxicont = conttext.getText().toString();
int maxcont = Integer.parseInt(maxicont);
UPDATE:
i get errors in:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button buttsave = (Button) findViewById(R.id.buttsave);
buttsave.setOnClickListener(new View.OnClickListener"here" {
public void onClick "here" {
Intent intent = new Intent(getApplicationContext(), GuessOne.class);
intent.putExtra("maxNumberPressed", conttext.getText());
startActivity(intent);
}
});
I get errors where i placed the "here" obviously it is not part of the code. It is only to see where the errors are.
You need to use Intents for that. A similar question was answered here:
Passing Values To Another Activity
When starting the other activity, make a bundle.
In the current activity, try:
Intent intent = new Intent(getApplicationContext(), <next activity>.class);
intent.putExtra("maxNumberPressed", editText.getText());
startActivity(intent);
Then in the next activity where you are using it, put this in onCreate method:
Bundle bundle = this.getIntent().getExtras();
String maxPressed = bundle.getString("maxNumberPressed");
Create a button with text as 'save' or something. then do:
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener{
public void onClick() {
Intent intent = new Intent(getApplicationContext(), <next activity>.class);
intent.putExtra("maxNumberPressed", editText.getText());
startActivity(intent);
}
});
How to pass data from an Activity to another can vary a lot, depending on how the Activities are related.
If you are passing data from a parent to a child Activity, you pass the information through an Intent when starting the new child Activity. Here's how you send the information:
itt = new Intent(this, ChildActivityName.class); // Create new Intent
itt.putExtra("MAX", maxcont); // Fill Intent with data
startActivity(itt, SOME_NUMBER_IDENTIFYING_THE_PARENT); // Start Activity
And here's how the receiving child Activity retrieves it:
void onCreate(Bundle savedInstanceState) {
...
Intent itt = getIntent(); // Grab the Intent created with this Activity
int maxcont = itt.getIntExtra("MAX", -1); // Retrieve data, default is -1
}
If you are passing data the other way, from a child to a parent Activity, the simplest way to pass through using startActivityForResult. The parent starts the child activity using this command:
startActivityForResult(itt, SOME_NUMBER_IDENTIFYING_THE_PARENT);
The Child then passes the information back to the parent just before it exits:
Intent itt = new Intent(); // Create new Intent
itt.putExtra("MAX_RETURN", maxcont); // Add data to the Intent
setResult(RESULT_OK, itt); // Signal to parent valid result
finish(); // End this Activity
Once the child calls finish(), the parent's onActivityResult() method will be invoked:
protected void onActivityResult(int requestCode, int resultCode, Intent itt) {
maxcont = data.getIntExtra("MAX_RETURN", -1); // defaults to -1
...
}
The Strings used in putExtra and getIntExtra are identifying keys for associated data, which are used all over the place in Android programming and beyond the scope of this question. Just make sure that the sender and the receiver of the data through the Intents use the EXACT same string!
If you need to pass information between two sibling Activities that are both active, the easiest way is through static public variables in each Activity. That's pretty basic; you should have no problem with these.
If you need to pass information between two sibling Activities that may or may not be Active, then you need to use a Broadcast/Receiver paradigm. But I think that method is overkill for what you are talking about.

Make my class take an argument

Well I have a main Screen with 5 buttons. Each time a press a button I want to go a new screen. So far I have other 5 classes (each for each screen) and 5 xmls. But Iam sure that there will be a better way beacuse this screen and the xmls are the same, and what I want to do is change some texts and some data I fetch from a database. I am sure that I can ony another class and only one xml and then pass the values that I want as arguments. (Imagine that in its final state my app must have 15 buttons, so I think it is too mych waste of space and unnecessary to have 15 .java files and 15 xml files that look the same and only some values of images and textviews change). My code for main activity is:
public class MyActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
main2Theme();}
private void main2Theme() {
setContentView(R.layout.main_new);
Button Button100 = (Button)findViewById(R.id.Button100);
Button113.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Intent i = new Intent(this, OtherScreenName.class);
startActivity(i);
}
}); //and so on for 15 buttons
My OtherScreenName.class is:
public class OtherScreenName extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Theme();
}
#SuppressWarnings("null")
private void Theme() {
Log.d("SnowReportApp","Do first thing");
setContentView(R.layout.otherscreenname); //THIS CHANGES IN EVERY CLASS DEPENDING ON THE ID OF THE BUTTON
String result = "";
InputStream is = null;
StringBuilder sb=null;
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();//() before
nameValuePairs.add(new BasicNameValuePair("ski_id","OtherScreenName"));
TextView text1 = (TextView) findViewById(R.id.otherscreenname_1);
//THESE 2 CHANGE DEPERNDING ON THE BUTTON PRESSED
//perform action.....
//AND ALSO HERE I NEED THE ID OF THE BUTTON
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent i = new Intent(OtherScreenName.this,MyActivity.class);
startActivity(i);
}
});
Can anyone suggest how to give arguments to my class and what it should be the type of them?
If I understand your question correctly, you want to pass arguments to the activity. Normally it would be done through the class constructor, however, activities can't have user defined constructors, only the default one; they can be instantiated only indirectly via intent creation. If you need to pass data between activities, do it by putting extras to bundles, for example:
bundle.putInt("intName",intValue);
then you can extract the data from bundle by
int intValue = bundle.getInt("intName");
Put extras before starting the activity:
Intent i = new Intent(this, YourActivity.class);
Bundle b = new Bundle();
b.putInt("intName",intValue);
i.putExtras(b);
startActivity(i);
and then read the extras in the onCreate method:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle b = getIntent().getExtras();
int intValue;
if (b != null)
{
intValue= b.getInt("intName");
}
}
The same way you can pass other data types as String boolean etc. If this is not sufficient and you need to pass some more complex data, then use Parcelable interface.
You can pass parameters with an Intent by adding extra's to it, something like the following:
Intent i = new Intent(this, MyActivity.class);
i.putExtra("paramName", "value");
startActivity(i);
In your activity you can use the getIntent() method to retrieve the Intent and extract your parameter(s) from it:
Intent i = getIntent();
Bundle extras = i.getExtras();
String param = extras.getString("paramName", "default value");
You can place all the different text and data in your Intent, but you can also decide based on the value of an Intent parameter which data and text to retrieve. If it is a lot of data or text you are probably better off using the second approach.
If you want to pass object instead of simple data, you must use parcelable objects as it´s explained in: [http://developer.android.com/reference/android/os/Parcelable.html][1]
Reading and writing with parcelable objects is very similar to the way with a simple data
Intent intent = new Intent(this ,newthing.class);
Bundle b = new Bundle();
b.putParcelable("results", listOfResults);
intent.putExtras(b);
startActivityForResult(intent,0);
Intent i = getIntent();
Bundle extras = i.getExtras();
String param = extras.getParcelable("results");

Passing data between activities

I have the following code:
chart.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final String aux= (String) lt.getItemAtPosition(position);
Intent myIntent = new Intent(infoList.this, tabList.class);
startActivity(myIntent);
}
});
I also have a ListView. When I click on an item from that ListView I navigate to another activity that shows me the info for that activity. How do I do that? I want that info to correspond to the item I clicked.
Here is what I did in this situation, if you don't want to just pass an id back:
I call the other activity with this:
Intent intent = new Intent(myapp, CreateExerciseActivity.class);
intent.putExtra("selected_id", workout.getId());
startActivityForResult(intent, CREATE_ACTIVITY);
I then do
Intent returnIntent = new Intent();
returnIntent.putExtra("name", m.getName());
returnIntent.putExtra("unit", m.getUnit());
returnIntent.putExtra("quantity", m.getQuantity());
if (getParent() == null) {
setResult(Activity.RESULT_OK, returnIntent);
} else {
getParent().setResult(Activity.RESULT_OK, returnIntent);
}
finish();
So, in this case I was passing in an id in order to get more details from the user, and then I pass those back to the calling activity, in order to add it, as I didn't want to save this until the user chooses to later.
So, you need to do startActivityForResult in order to have it able to return the data.
You can add some data to the Intent with the methods putExtra(), and then retrieve the data in the new Activity with getExtras().getSomething().
i guess you have to use OnItemClickListener instead of the click event and you need intent to call the next activity.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id)
{
Intent intent = new Intent(this, MyInfoActivity.class);
intent.putExtra("selected_id", getIdFor(position));
startActivity(intent);
}
};
mHistoryView = (ListView)findViewById(R.id.history);
mHistoryView.setOnItemClickListener(mMessageClickedHandler);
Possible answer: How do I pass data between Activities in Android application?
http://thedevelopersinfo.wordpress.com/2009/10/15/passing-data-between-activities-in-android/
It really depends on what the data is in your listview. For example, if you're displaying a list of contacts in the listview, you could just pass the ID of the contact over to the other activity, and let that activity access the content provider for contacts to retrieve the data you want it to work with. You'd pass an ID within a URI in the data field of the intent, as opposed to in the extras bundle.

Categories

Resources