Accessing an Instance's Variable from another Activity - Android Developement - android

I have creted a program that has 3 Activities: MainActivity, UpgradeActivity and UpgradesActivity.
Main Activity contains a timer and it also contains an instance of a Vehicle class.
public class MainActivity extends Activity {
TextView vehicleSpeed, vehicleName, vehicleDistance, vehicleLocation,
vehicleStatus, vehicleNews, vehicleInfo, vehicleMoney;
ProgressBar vehicleFuel;
public static Vehicle vehicle;
boolean launched;
public static PartType selectedType;
Handler handler = new Handler();
I have a button in MainActivity, that when pressed will take me to a page where i can select which part of the vehicle i wish to upgrade. For example i select: Engine. The engine Button takes me to the Upgrade Activity. In this activity i can buy the upgrade which should be applied to the vehicle in MainActivity. For the purpose of this question, lets say it set vehicles speed to +3.
My question is in regards to how to access the vehicle instance inside the MainActivity from the UpgradeActivity. I've tried making the instance static but that didn't work. How do i gain access and how can i change the vehicles variables from the other activities.
Here is where i am making the instance:
#Override
protected void onCreate(Bundle savedInstanceState) {
this.selectedType = PartType.Antenna;
this.launched = false;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vehicle = new Vehicle();
vehicle.setupCar();
Here is where i am accessing the variable in Upgrades, it call the upgrade function inside of the Vehicle Class:
buyUp1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
MainActivity.vehicle.upgradeEngine(MainActivity.vehicle.engineLvl + 1);
Intent activityChangeIntent = new Intent(UpgradesActivity.this, MainActivity.class);
UpgradesActivity.this.startActivity(activityChangeIntent);
}
});
And this is the function within the Vehicle Class:
public void upgradeEngine(int lvl) {
engineLvl += 3;
engine = parts.getEngine(lvl);
}
The vehicle Stores an integer called: EngineLvl. This determines what level the cars engine is. The level is incremented by +3 everytime the engine is updated.
The problem is that the engine level never changes. Even if i make the Vehicle instance and all of the variables within vehicle STATIC;
MAINACTIVITY:
Vehicle
Button to UpgradesActivity
UPGRADESACTIVITY:
Button to UpgradeActivity
UPGRADEACTIVITY:
Change vehicle enginelvl Int
Button back to MainActivity
Main>Upgrades>Upgrade
Thank you for your time

Hard to say what is wrong without seeing the code, but I would advise you to use the Intent extras to move your data between activities. You will need to make your Vehicle class implement Parcelable (there is an example of how to implement Parcelable on that page, and countless others on the net). You pass your object as extra to the intent launching your UpgradeActivity like this :
Intent upgradeIntent = new Intent(this, UpgradeActivity.class);
upgradeIntent.putExtra("com.example.model.Vehicle", yourVehicleObject);
startActivityForResult(upgradeIntent, UPGRADE_CAR_REQUEST_CODE);
//UPGRADE_CAR_REQUEST_CODE is a unique private static final int
Then you can retrieve it in your UpgradeActivity onCreate method :
Intent intent = getIntent();
Vehicle vehicleFromLastActivity = intent.getParcelableExtra("com.example.model.Vehicle");
Before going back to your MainActivity you do something like this :
Intent dataIntent = new Intent();
dataIntent.putExtra("com.example.model.Vehicle", yourModifiedVehicleObject);
setResult(RESULT_OK, dataIntent);
finish();
Then finally in MainActivity you need to handle the result, it is done like this :
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case UPGRADE_CAR_REQUEST_CODE:
if(resultCode == android.app.Activity.RESULT_OK) {
Vehicle modifiedObject = data.getParcelableExtra("com.example.model.Vehicle");
// Now you can use that object which is coming from UpgradeActivity
}
}
}
Of course this could cause issues if your Vehicle class takes a lot of memory. You could then consider passing only the relevant information through the Intent to rebuild the object in the UpgradeVehicle Activity, for example only the id & name.

Related

send Arraylist by Intent

How can I receive a custom ArrayList from another Activity via Intent? For example, I have this ArrayList in Activity A:
ArrayList<Song> songs;
How could I get this list inside Activity B?
The first part to understand is that you pass information from Activity A to Activity B using an Intent object, inside which you can put "extras". The complete listing of what you can put inside an Intent is available here: https://developer.android.com/reference/android/content/Intent.html (see the various putExtra() methods, as well as the putFooExtra() methods below).
Since you are trying to pass an ArrayList<Song>, you have two options.
The first, and the best, is to use putParcelableArrayListExtra(). To use this, the Song class must implement the Parcelable interface. If you control the source code of Song, implementing Parcelable is relatively easy. Your code might look like this:
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putParcelableArrayListExtra("songs", songs);
The second is to use the version of putExtra() that accepts a Serializable object. You should only use this option when you do not control the source code of Song, and therefore cannot implement Parcelable. Your code might look like this:
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putSerializableExtra("songs", songs);
So that's how you put the data into the Intent in Activity A. How do you get the data out of the Intent in Activity B?
It depends on which option you selected above. If you chose the first, you will write something that looks like this:
List<Song> mySongs = getIntent().getParcelableArrayListExtra("songs");
If you chose the second, you will write something that looks like this:
List<Song> mySongs = (List<Song>) getIntent().getSerializableExtra("songs");
The advantage of the first technique is that it is faster (in terms of your app's performance for the user) and it takes up less space (in terms of the size of the data you're passing around).
Misam is sending list of Songs so it can not use plain putStringArrayList(). Instead, Song class has to implement Parcelable interface. I already explained how to implement Parcelable painless in post here.
After implementing Parcelable interface just follow Uddhavs answer with small modifications:
// First activity, adding to bundle
bundle.putParcelableArrayListExtra("myArrayListKey", arrayList);
// Second activity, reading from bundle
ArrayList<Song> list = getIntent().getParcelableArrayListExtra("myArrayListKey");
I hope this helps you.
1. Your Song class should be implements Parcelable Class
public class Song implements Parcelable {
//Your setter and getter methods
}
2. Put your arraylist to putParcelableArrayListExtra()
public class ActivityA extends AppCompatActivity {
ArrayList<Song> songs;
#Override
protected void onCreate(Bundle savedInstanceState) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), ActivityB.class)
.putParcelableArrayListExtra("songs", (ArrayList<? extends Parcelable>) songs));
}
});
}
3. In the ActivityB
public class ActivityB extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
Intent intent = getIntent();
final ArrayList<Song> songs = intent.getParcelableArrayListExtra("songs");
//Check the value in the console
buttonCheck.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (Song value : songs) {
System.out.println(value.getTitle());
}
}
});
}
to send a string arrayList in Java you can use,
intent.putStringArrayListExtra("key", skillist <- your arraylist);
and
List<String> listName = getIntent().getStringArrayListExtra("key");
Please note, bundle is one of the key components in Android system that is used for inter-component communications. All you have to think is how you can use put your Array inside that bundle.
Sending side (Activity A)
Intent intent1 = new Intent(MainActivity.this, NextActivity.class);
Bundle bundle = new Bundle();
Parcelable[] arrayList = new Parcelable[10];
/* Note: you have to use writeToParcel() method to write different parameters values of your Song object */
/* you can add more string values in your arrayList */
bundle.putParcelableArray("myParcelableArray", arrayList);
intent1.putExtra("myBundle", bundle);
startActivity(intent1);
Receiving side (Activity B)
Bundle bundle2 = getIntent().getBundleExtra("myBundle"); /* you got the passsed bundle */
Parcelable[] arrayList2 = bundle.getParcelableArray("myParcelableArray");

What is the right way to hold and restore the data temporarily between activities in android?

I am creating an Android app. One of the functions is to collect some data (item name, item ID and the barcode string) from the user .
Activity1 is a form. User enters the item name and item number manually. For the barcode string, user clicks on the "scan" button then Activity2 (Scanner) is started in order to scan and read the barcode. Once the barcode is read, Activity1 (the form) starts again and all data should appear on the form.
When Activity2 starts by Intent, Activity1 is killed. So, I have to get the item name and item number and store them temporarily before staring the Intent. Then when Activity1 starts again, those data will be rendered on the form again.
Now I am thinking to use Intent Extra to keep the item name and number, and pass them to Activity2 and back to Activity1. Given that Activity2 doesn't need those data, I wonder if that is the right way to do in this scenario. Is there any better way? Should I use Shared Preferences instead?
In Your first activity use put extra argument to intent like this:
// Assuming Activity2.class is second activity
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("variable_name", var); // here you are passing var to second activity
startActivity(intent);
Then in second activity retrieve argument like this:
String var2 = getIntent().getStringExtra(variable_name);
You could create a singleton class and expose setter(for saving) and getter (for retrieving) methods for the model objects (here two private string variables).This class will be alive with your application:
public class MyClass{
private static MyClass instance=null;
public static getInstance(){
if(instance==null){
instance=new MyClass();
}
return instance;
}
private String itemName;
private String itemNumber;
//setter and getter methods here
}
why need to kill the Activity 1, try to call
on Activity 1
declare private int SCAN_BARCODE_REQUEST = 101;
and then
//finish(); dont use this to destroy activity 1
startActivityForResult(new intent(this,Activity2.class), SCAN_BARCODE_REQUEST);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SCAN_BARCODE_REQUEST) {
if (resultCode == RESULT_OK) {
String barcode = data.getStringExtra("BARCODE");
//handle your barcode string here
}
}
}
on your Activity 2,
change your start Activity1 with
Intent intent = new Intent();
intent.putExtra("BARCODE", barcodeString);
setResult(RESULT_OK, intent);
finish();
You can use SharedPreferences.
You can learn how to use them here:
https://www.tutorialspoint.com/android/android_shared_preferences.htm
https://developer.android.com/training/basics/data-storage/shared-preferences.html
SharedPreferences is a really good solution for such applications. It is very simple and easy to use and implement.

OnActivityResult when having GUI parts outside Fragment

I have a two pane fragment design with the detail fragment dealing with the item clicked on the leftmost, listfragment.
Since I have many different list items, they have different GUI's each one of them, I want to put the handling of the GUI parts in different separate classes.
I'm using reflections to get the code slimmed inside the ItemDetailFragment:(code below is stripped down)
*//get class gui_handler for the object and get its constructor:*
Constructor<?> ctor = mListItem.getmGuiHandler().getConstructor(View.class);
*//create an object of the gui_handler class, pass the rootView as arg:*
gui_handler_base handlerObject = (gui_handler_base) ctor.newInstance(root);
*//run setup-method containing findViewById() and more GUI related stuff:*
handlerObject.setupGUI(mListItem, getActivity());
In setupGUI:
public void setupGUI(MyListItem item, final Activity activity) {
buttonRun.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
final String FILENAME = "XXX";
Intent I = new Intent(activity,KTActivity.class);
Bundle b = new Bundle();
b.putSerializable("FileName",FILENAME);
I.putExtras(b);
activity.startActivityForResult(I,1);
return;
}
});
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
// I WANT TO END UP HERE WHEN THE ACTIVITY RETURNS;
}
I have one onActivityResult method in the gui_handler_base class and one in the ItemDetailFragment, but none of them are called.
How can I do this??
Your question is quite ambiguous. Why are you using onActivityResult? activity.startActivityForResult(I,1); why? WHy not just implement the onclicklistener class in your fragment class and be done with it? It seems like in trying to reduce code you created more headaches for yourself. Also take out numbers in your code and use constants. You have to call the intent and use the intent in the same fragment. Further more why are you extracting out the GUI functionality from the fragments? You shouldn't be. even if you are creating custom functionality, you would still deal with a fragment's functionality in the fragment.
//if you want to try this… normally when receiving a camera intent this is what you can do.
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case yourResultCode:
doSomethingWithYourResult;
break;
]

transfeer object between activities

I`m trying to parse an object from my my main activity to a new activity that starts when the user clicks a button. I've seached the internet and found how to parse primative types and custom made classes that implements parceble or serilizable, but can't find any information on how to transfeer a raw object.
I'll write psuedo-code of what I`m trying to achive below:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loadConnectInfo();
View connectButton = findViewById(R.id.connectButton);
connectButton.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.connectButton:
Intent i = new Intent(this, NewClass.class);
Socket s = connect(); // this is the object I want to parse to to "NewClass"
startActivity( i);
break;
}
You can't pass an object that is neither serializable nor parcelable between activities this way. What you probably want to do in this case is make your code that manages and interacts with the socket into a service and bind to that service in all the activities that need to use it.
Sometimes when I had to pass variable from one class to another I've used static variables in class which I deliver some objects. This will work but it is not recommended way to pass object in Android and you don't have guaranty that will work always.. Here you should check if your delivered object is not null of course.
public void onClick(View v) {
switch (v.getId()) {
case R.id.connectButton:
Intent i = new Intent(this, NewClass.class);
Socket s = connect(); // this is the object I want to parse to to "NewClass"
//Here using static field of class you pass variable to NewClass
//You can access this value in NewClass like that: NewClass.StaticSocket
//Warning: This is not a standar android scheme but I tested and it works
//with Date object
NewClass.StaticSocket = s;
startActivity( i);
break;
}
On second activity:
public void onCreate(Bundle savedInstanceState) {
Log.i("StaticVar","NewClass.StaticSocket: "+ NewClass.StaticSocket.toString());
There are already other posts about this:
What's the best way to share data between activities?
BTW, be careful: objects like sockets are not meant to be shared by bundles through the intent because they shouldn't be serialized. Maybe using a global state, like a singleton does it for you.

Android - How to retrieve data from activity

I am new to android so please excuse the newbie question. I have a game I am trying to port from an old Java applet to android. My goal is to get this functional and then post an article on a site like CodeProject (or a better one if there are ones more appropriate). The idea is to show that a person brand new to android development can create an app in a reasonable amount of time.
I am making some progress but have run into a problem. I have the main activity in which the user interacts with. I then created a menu item that in turn starts a second activity (call it child) with a modest number of checkbox's, seekbar's etc to fill in parameters. I can successfully pass the class containing all the options from main to child. But I cannot get the child to pass this data back to the main.
First here is my main code that starts the child activity:
public void addBalls()
{
Intent myIntent = new Intent(this, GameOptions.class);
Bundle b = new Bundle();
b.putSerializable("options", gameParams);
myIntent.putExtras(b);
startActivityForResult(myIntent,STATIC_OPTIONS_VALUE);
}
The data passed to the child (and hopefully back again) is:
public class GameOptionParams implements Serializable
{
private static final long serialVersionUID = 1L;
public int speedBarPosition;
public int vgravityBarPosition;
public int mgravityBarPosition;
public int viscosityBarPosition;
public int restititionBarPosition;
public boolean trace;
public boolean collide;
public boolean mush;
public boolean wrap;
public boolean flicker;
}
And here is the expected return (again in main)
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case (STATIC_OPTIONS_VALUE) :
{
if (resultCode == Activity.RESULT_OK)
{
//retrieve intended options
Bundle b = data.getExtras();
gameParams = (GameOptionParams) b.getSerializable("options");
}
break;
}
}
}
The child activity successfully receives the gameParams data. It then interacts with the user to update the values and then I attempt to return it but it does not seem to get sent to main. Here is the child code in the onStop() override.
Maybe this code should not be in the onStop() override but I can't determine where else to place it.
#Override
public void onStop()
{
super.onStop();
//read widget values
gameParams.speedBarPosition = speedBar.GetPosition();
gameParams.vgravityBarPosition = vgravityBar.GetPosition();
gameParams.mgravityBarPosition = mgravityBar.GetPosition();
gameParams.viscosityBarPosition = viscosityBar.GetPosition();
gameParams.restititionBarPosition = restititionBar.GetPosition();
//todo save to persistent
Intent resultIntent = new Intent(this, TiltBall2ImpactActivity.class);
Bundle b = new Bundle();
b.putSerializable("options", gameParams);
resultIntent.putExtras(b);
setResult(Activity.RESULT_OK, resultIntent);
}
Back in the main onActivityResult override I always see requestCode=0, resultCode=0, data=null. I assume this is a typical newbie problem, I have been reading the sdk documentation, user forums etc and have come close to a solution but just not quite there yet. Any help would be appreciated.
Since this is sort of a setting menu for the game, I assume you are going to need these values for more than one activity. If so you extend the android.app.Application class.
In that class you can create attributes to hold your values. In any activity you can call
MyApplication myApp = (MyApplication)getApplicationContext();
where myApp is a singleton. So you will get the values you set from another activity.
You will need to add this code to your application tag in the manifest file for it to work
android:name=".MyApplication"
If you need to keep these values for next startup of the application, you need to use SharedPreferences. This is a good tutorial for that
http://saigeethamn.blogspot.com/2009/10/shared-preferences-android-developer.html
Assuming in your 'child' activity, the user has to press an 'OK' or 'Save' button then put the code to set the gameParams parameters in the button's onClick(...) handler.
Use the default constructor for instantiating the Intent, example...
Intent resultIntent = new Intent();
...then after creating the Bundle and adding gameParams to it and calling setResult(...), simply call finish() to terminate the 'child' activity. There aren't many occasions that I can think of to override onStop() and I suspect you don't want to be using it to attempt returning the Intent.

Categories

Resources