Passing Data Between Activities in Android App - java

Hey I am pretty new to making android apps and I understand that the easiest way to pass data between two activities is through an intent.
In one of my classes (EventOptions.java), I call this line of code:
Intent i = new Intent(EventOptions.this, PhotoFetcher.class);
i.putExtra("imageArray", imageIDs);
startActivity(i);
imageIDs is a string array
In my PhotoFetcher class, I want to set a string array called imageIDs to the imageIDs string array that I am passing through the intent.
I want to set images as a global variable in my class:
public class MainActivity extends Activity implements View.OnClickListener{
Intent it = getIntent();
String[] imageIDs = it.getStringArrayExtra("imageArray");
...
}
This crashes my app however. Is this not allowed? And if so, how can I fix it? Thanks in advance!

Need to call getIntent() in a method instead of at class level. call it inside onCreate :
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// get Intent here
Intent it = getIntent();
String[] imageIDs = it.getStringArrayExtra("imageArray");
}
if I want to use the imageIDs array in another public class defined
in my PhotoFetcher class, do I need to call it again?
To get imageIDsin PhotoFetcher class either declare String[] imageIDs as global variable or pass imageIDs using PhotoFetcher class constructor

You have to use putStringArrayListExtra. You can convert your String[] to an ArrayList first.
Like so
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(imageIDs));
Intent i = new Intent(EventOptions.this, PhotoFetcher.class);
i.putStringArrayListExtra("imageArray", arrayList);
startActivity(i);
And then you can fetch it like you do, preferably in onCreate or after that call.
Intent it = getIntent();
ArrayList<String> imageIDs = it.getStringArrayListExtra("imageArray");

Share data without persisting to disk
It is possible to share data between activities by saving it in memory given that, in most cases, both activities run in the same process.
Note: sometimes, when the user leaves your activity (without quitting it), Android may decide to kill your application. In such scenario, I have experienced cases in which android attempts to launch the last activity using the intent provided before the app was killed. In this cases, data stored in a singleton (either yours or Application) will be gone and bad things could happen. To avoid such cases, you either persist objects to disk or check data before using it to make sure its valid.
Use a singleton class
Have a class to whole the data:
public class DataHolder {
private String data;
public String getData() {return data;}
public void setData(String data) {this.data = data;}
private static final DataHolder holder = new DataHolder();
public static DataHolder getInstance() {return holder;}
}
From the launched activity:
String data = DataHolder.getInstance().getData();
Use application singleton (I would recommend this)
The application singleton is an instance of android.app.Application which is created when the app is launched. You can provide a custom one by extending Application:
import android.app.Application;
public class MyApplication extends Application {
private String data;
public String getData() {return data;}
public void setData(String data) {this.data = data;}
}
Before launching the activity:
MyApplication app = (MyApplication) getApplicationContext();
app.setData(someData);
Then, from the launched activity:
MyApplication app = (MyApplication) getApplicationContext();
String data = app.getData();

ρяσѕρєя K hit the nail on the head, you're running a method where constructors and fields go. To make the variables (the imageIDs) global, it's quite simple and there are a few ways of doing it. Declare them outside any method, and then assign them in your onCreate or onResume (which will always be called).
Try this:
public class MainActivity extends Activity implements View.OnClickListener {
//global variable
String[] imageIDs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get Intent here
Intent it = getIntent();
imageIDs = it.getStringArrayExtra("imageArray");
}
}

Related

How to get Intent values non Activity Class in Android

I am new to Android. I have a base Activity class (MainActivity.java) which extends Activity. So I can initialized Intent here.
MainActivity.java
Intent myIntent = new Intent(MainActivity.this, ConnectionClass.class);
myIntent.putExtra("ServerName", ServerName);
startActivityForResult(myIntent, 1);
In connectionClass.java I have a class ConnectionClass which doesn't inherited. But I want to access the values from MainActivity.java. So this class Doesn't inherited Activity & onCreate Method. But I need to access the values from MainActivity.java to ConnectioClass.java
ConnectionClass.Java
public class ConnectionClass {
Bundle bundle = getIntent().getExtras();
String ServerName = bundle.getString("ServerName");
}
How can I do this?
I don't know if the "ServerName" is fixed value, or varies each time, or it has a kind of pool of values. If it's the first or third case, I suggest you to use SharedPreferences. It's a relatively small key-value data storage. You can save data in it and it will be permanent in your app once stored unless deleted. So you can save data in MainActivity, and fetch the value in a class wherever you want.
You can find tutorial here : https://developer.android.com/training/basics/data-storage/shared-preferences.html
you can pass the servername to the class when you are instantiating a new object from ConnectionClass in your activity like below
public class ConnectionClass {
String serverName;
public ConnectionClass(String serverName){
this.serverName=serverName;
}
}
then in your activity you have something like:
Bundle bundle = getIntent().getExtras();
String ServerName = bundle.getString("ServerName");
ConnectionClass connection=new ConnectionClass(ServerName);

How can I go to second activity but send a data to another activity?

I made an application "Quiz", which has 4 activities. Main activity sends a String with your name from EditText to activity with first question. I have a problem here, because I don't know how to send this string immediately to final activity from main activity, but without going to final activity. I want to go to Activity with first question from main activity, then to activity with second question, and in the end I want to go to final activity.
Thanks for your help!
You could use static fields to pass data.
Inside your FinalActivity class you could add the following variable:
private static String NAME = "";
And with the following getters and setters:
public static String getName(){
return NAME;
}
public static void setName(String name){
NAME = name;
}
You can use the getter setter here at Application class so you can get the string data from anywhere were you want to. This is not the only way but i think it is also the easy way.
public class MyApplication extends Application {
private String someVariable;
public String getSomeVariable() {
return someVariable;
}
public void setSomeVariable(String someVariable) {
this.someVariable = someVariable;
}
}
add this in your manifest
<application
android:name=".MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name">
hen in your activities you can get and set the variable like so:
/ set
((MyApplication) this.getApplication()).setSomeVariable("foo");
// get
String s = ((MyApplication) this.getApplication()).getSomeVariable();
Some Url which may help you Android global variable
You can use shared preference also but as per our requirement i don't recommend that to you
Android Shared preferences example
You can use Broadcast Receiver for your requirement. In your activity from which you want to send data, do this way:
Intent intent = new Intent();
intent.setAction("fourthactivity");
sendBroadcast(intent);
And In your fourth activity, make a broadcast receiver which receive your intent :
public class IncomingReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("fourthactivity")) {
System.out.println("GOT THE INTENT");
}
}
}
Tell me if this doesn't work or click right if it works for you.
You can use SharedPreference to store the answers as you go from one activity to other and later compare all the answers in the FinalActivity in that way less complex coding and you will achieve your desired result.

Editing and saving an ArrayList<> that has been passed to another activity

I am making a frisbee logger and have an ArrayList of Team objects. Each Team has an ArrayList of Player objects. Everything is using Serializable properly to be sent using Intent.
In my main activity I am displaying the list of Team objects in a ListView and an option to add another Team (only a name is needed). Once a Team is selected I pass the object to another activity using Intent. On this second activity I have it display the list of Player objects and have fields to enter another player object into the passed list.
When I return to the main activity and go back to the add Player activity, what I have added is gone.
I cannot use static because there is obviously more than one Team object. I think passing back the changed ArrayList could work but that seems a little lame, time-consuming, and frustrating.
Is there a built-in way in Android Studio that does this or am I on my own?
Note: I am not using SQLite as suggested in the comments
There's not a whole lot to show on this but here it is I guess:
MainActivity.java
private static ArrayList<Team> listOfTeams = new ArrayList<>();
private static ArrayList<Game> listOfGames = new ArrayList<>();
private ListView gameList, teamList;
.....
teamList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Team t = (Team)teamList.getItemAtPosition(position);
viewTeam(t);
}
});
.....
//Item select in teamList. Start the TeamViewActivity
public void viewTeam(Team t)
{
Intent i = new Intent(this, TeamViewActivity.class);
i.putExtra("teamView",t);
startActivity(i);
}
TeamViewActivity.java
private Team team;
private ListView rosterList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_team_view);
rosterList = (ListView) findViewById(R.id.playerList);
Intent i = getIntent();
Bundle extras = i.getExtras();
if(extras!=null)
{
if(extras.get("teamView")!=null)
{
team = (Team) extras.get("teamView");
}
}
populateRosterList(team.getRoster());
}
public void addPlayerToRoster(View view)
{
String checkFirst = ((EditText) findViewById(R.id.firstText)).getText().toString();
String checkLast = ((EditText) findViewById(R.id.lastText)).getText().toString();
String checkNumber = ((EditText) findViewById(R.id.numberText)).getText().toString();
if(!checkNumber.equals(""))
{
team.addPlayer(checkFirst, checkLast, Integer.parseInt(checkNumber));
((EditText) findViewById(R.id.firstText)).setText("");
((EditText) findViewById(R.id.lastText)).setText("");
((EditText) findViewById(R.id.numberText)).setText("");
populateRosterList(team.getRoster());
}
}
public void returnToMain(View view)
{
Intent i = new Intent(this, MainActivity.class);
i.putExtra("teamView", team);
startActivity(i);
}
private void populateRosterList(ArrayList<Player> list)
{
ArrayAdapter<Player> adapter = new ArrayAdapter<>(this,
R.layout.activity_list, R.id.genericText, list);
rosterList.setAdapter(adapter);
}
Consider your concept:
You serialize an object, i.e. you transform it into a transferrable format which is then copied over to the other activity and reconstructed as a new instance.
Consequently, you alter another instance, which is not available in the previous activity, if you do not return it - again, serialized - and finally reconstruct and copy it back into the respective instance.
What you need is a shared memory storage in your application, which can alter and retrieve data cross-activity OR a proper data routing using Intents w/ ISerializable.
Options:
Always serialize objects and pass and copy them around.
-> No multithreaded alteration, possibly slow, unbeautiful
Singleton application with global data storage ir Context Object (I do NOT recommend the due to memory management and Garbage
Collection inbetween Activity Switches BUT for consistency I'd
wanted to mention this option)
SQLite3
-> Quick, Simple and Scalable, But a bit cumbersome to get started with
Any other file-structure stored and maintained in the data folder
-> I'd expect a lot of boilerplate code here, and low performance
Webservice and remote database
Proper component setup, i.e. initialize all accessing components in your software with the appropriate reference to the data structs using for example fragments (Thanks to #mismanc, I actually missed that option initially)
In general you could abstract all that away using services and repositories, which allows you to under-the-hood test options like 3. 4. And 5. and find your best solution, and in addition, keeo the accessing code simple and clean.
in your case, you can use startActivityForResult instead of startActivity, then get your modified Team object from onActivityResult(int requestCode, int resultCode, Intent data) to update your list.
startActivityForResult example
You can use fragments. You hold the list in the MainActivity and pass its reference to ShowListFragment and AddPlayerFragment by interfaces. And you can also do other operations over them. If you dont want to use json or sqlite it can be a good way for you.
MainActivity.java
public class MainActivity extends Activity implements ShowListener{
public interface ShowListener{
ArrayList<Team> getTeamList();
}
private ArrayList<Team> listOfTeams = new ArrayList<>();
#Override
public ArrayList<Team> getTeamList() {
return listOfTeams;
}
}
ShowListFragment.java
public class ShowListFragment extends Fragment {
private ArrayList<Team> listOfTeams;
private ShowListener listener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listener = (ShowListener)getActivity();
listOfTeams = listener.getTeamList();
}
}
As #Kingfisher Phuoc mentioned you could use srartActivityForResult in case you don't want to change your approach.
Otherwise I will suggest you use either :
SharedPreference to store your arraylist object (by converting the arraylist to json then store it as string in json format). In the PlayerActivity you retrieve the data, manipulate it then save it. see this post
SQLite

android activity class constructor working

When considering the case with android activity, the first method to work is its onCreate method..right?
Suppose i want to pass 2 parameters to android activity class say UserHome . For that am creating the constructor of activity class UserHome and accepting the params.
But when we are calling an activity we are not initializing the Activity class, we are just creating an intent of UserHome class.
Then how can we pass params to that activity from another activity without using intent.putExtra("keyName", "somevalue"); usage.
Experts please clarify how we can cover a situation like this.?
Not sure why you would not want to use the intent params. That is what they are there for. If you need to pass the same parameters from different places in your application, you could consider using a static constructor that builds your intent request for you.
For example:
/**
* Sample activity for passing parameters through a static constructor
* #author Chase Colburn
*/
public class ParameterizedActivity extends Activity {
private static final String INTENT_KEY_PARAM_A = "ParamA";
private static final String INTENT_KEY_PARAM_B = "ParamB";
/**
* Static constructor for starting an activity with supplied parameters
* #param context
* #param paramA
* #param paramB
*/
public static void startActivity(Context context, String paramA, String paramB) {
// Build extras with passed in parameters
Bundle extras = new Bundle();
extras.putString(INTENT_KEY_PARAM_A, paramA);
extras.putString(INTENT_KEY_PARAM_B, paramB);
// Create and start intent for this activity
Intent intent = new Intent(context, ParameterizedActivity.class);
intent.putExtras(extras);
context.startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Extract parameters
Bundle extras = getIntent().getExtras();
String paramA = extras.getString(INTENT_KEY_PARAM_A);
String paramB = extras.getString(INTENT_KEY_PARAM_B);
// Proceed as normal...
}
}
You can then launch your activity by calling:
ParameterizedActivity.startActivity(this, "First Parameter", "Second Parameter");
I can see one situation where you'd be unable to use the standard method of passing the parameters via the Intent: When you're creating an activity that will be launched by another app (say, the edit activity of a Tasker plugin) and, therefore, do not have control over the Intent that will launch your activity.
It's possible to create an Activity that accepts parameters in its constructor. The trick to using it, though, is not to use it directly, but to use a derived class with a default constructor that calls super() with the appropriate arguments, as such:
class BaseActivity extends Activity
{
public BaseActivity(String param1, int param2)
{
// Do something with param1 and param2.
}
// Many more lines of awesomeness.
}
class DerivedActivity extends BaseActivity
{
public DerivedActivity()
{
super("param1", 42);
}
}
Naturally, if you need to generate the parameters to pass to BaseActivity(), you can simply replace the hard-coded values with function calls.
We can pass the value from parent activity to child activity using the bundled collection and shared preference.
1. Shared Preference
2. Bundle Collection
Passing data or parameter to another Activity Android
But you also can create very well a constructor of UserHome.
public class MainActivity extends Activity {
UserHome userHome = new UserHome(param1,param2);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
userHome.yourMethod();
}}
Why do you think that is not possible to initialize a contructor?..MainActivity is a class like any other, just that extends Activity, but also keeps the properties of a class, so that can have, constructors, methods, members.

Passing custom objects between activities?

How do I pass custom objects between activites in android? I'm aware of bundles but I can't seem to see any functionality for this in them. Could anyone show me a nice example of this?
You should implement Parcelable interface.
Link to documentation.
Using Parcelable interface you can pass custom java object into the intent.
1) implement the Parcelable interface to your class like:
class Employee implements Parcelable
{
}
2) Pass the Parcelable object into the intent like:
Employee mEmployee =new Employee();
Intent mIntent = new Intent(mContect,Abc.class);
mIntent.putExtra("employee", mEmployee);
startActivity(mIntent);
3) Get the data into the new [Abc] Activity like:
Intent mIntent = getIntent();
Employee mEmployee = (Employee )mIntent.getParcelableExtra("employee");
a Parcel MIGHT solve your problem.
think of a Parcel as an "array" (metaphorical) of primitive types (long, String, Double, int, etc). if your custom class is composed of primitive types ONLY, then change your class declaration including implements Parcelable.
you can pass a parcelable object thru an intent with no difficulty whatsoever (just like you would send a primitive-typed object). in this case i have a parcelable custom class called FarmData (composed of longs, strings and doubles) which i pass from one activity to another via intent.
FarmData farmData = new FarmData();
// code that populates farmData - etc etc etc
Intent intent00 = new Intent(getApplicationContext(), com.example.yourpackage.yourclass.class);
intent00.putExtra("farmData",farmData);
startActivity(intent00);
but retrieving it may be tricky. the activity that receives the intent will check if a bundle of extras was send along with the intent.
Bundle extras = getIntent().getExtras();
FarmData farmData = new FarmData();
Intent intentIncoming = getIntent();
if(extras != null) {
farmData = (FarmData) intentIncoming.getParcelableExtra("farmData");// OK
}
Given an object PasswordState that implements Serializable throughout the object tree, you can pass this object to anther activity as in:
private void launchManagePassword() {
Intent i= new Intent(this, ManagePassword.class); // no param constructor
PasswordState outState= new PasswordState(lengthKey,timeExpire,isValidKey,timeoutType,"",model.getIsHashPassword());
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outState);
i.putExtras(b);
startActivityForResult(i,REQUEST_MANAGE_PASSWORD); // used for callback
}
One simple way to pass an object between activities or make a object common for all applicattion, is create a class extending Application.
Here is a example:
public class DadosComuns extends Application{
private String nomeUsuario="";
public String getNomeUsuario() {
return nomeUsuario;
}
public void setNomeUsuario(String str) {
nomeUsuario = str;
}
}
In all your others activities, you just need instantiate one object "DadosComuns", declarating as a Global Variable.
private DadosComuns dadosComuns;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//dados comuns
dadosComuns = ((DadosComuns)getApplicationContext());
dadosComuns.setNomeUsuario("userNameTest"); }
All others activities that you instantiate dadosComuns = ((DadosComuns)getApplicationContext()); you can acess getNomeUsuario() == "userNameTest"
In your AndroidManifest.xml you need to have
<application
android:name=".DadosComuns"

Categories