Taking data from one activity and storing it in another - java

I am trying to build a very simple App in Android Studio to practice using Intents to send data from one activity to another. On my Main Activity I have a "Total" TextView and a button. When I click the button, it takes me to a AddNumber Activity where I can type in an integer and press a button. This then takes me back to the Main Activity and adds that integer to the total, updating the TextView. I want to be able to do this multiple times while I've got the app open so the total keeps going up.
I have tried using a ViewModel to store the information so it doesn't get reset every time the Main Activity onCreate method is run. However, every time I do this, it works once (e.g. if I add a 7 in my AddNumber Activity, the Main Activity total goes to 7). However, when I try again, the ViewModel seems to get reset so doesn't remember the 7 that I put in initially, so if I put in an 8, the total on the MainActivity just gets set to 8, rather than 15. Am I making a mistake somewhere that is causing the ViewModel to reset? I understood that ViewModels were a way of storing data while the app is open, but I can't seem to make it work.
Thanks so much!
MainActivity.java code:
public class MainActivity extends AppCompatActivity {
TextView totalTextView;
MainActivityViewModel viewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
totalTextView = (TextView) findViewById(R.id.totalTextView);
viewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
totalTextView.setText(Integer.toString(viewModel.total));
getSetIncomingIntent();
}
public void addNumber(View view){
Intent intent = new Intent(this, AddNumber.class);
startActivity(intent);
}
public void getSetIncomingIntent() {
Intent incomingIntent = getIntent();
if (incomingIntent.hasExtra("value")) {
viewModel.newValue = incomingIntent.getIntExtra("value",0);
viewModel.addNumber();
totalTextView.setText(Integer.toString(viewModel.total));
}
}
}
MainActivityViewModel.java code:
public class MainActivityViewModel extends ViewModel {
int total = 0;
int newValue;
public void addNumber() {
total = total + newValue;
}
}
AddNumber.java code:
public class AddNumber extends AppCompatActivity {
EditText numberEditText;
int value;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_number);
numberEditText = (EditText) findViewById(R.id.numberEditText);
}
public void addNumber(View view){
value = Integer.parseInt(numberEditText.getText().toString());
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("value", value);
startActivity(intent);
}
}

When I click the button, it takes me to a AddNumber Activity where I can type in an integer and press a button. This then takes me back to the Main Activity and adds that integer to the total, updating the TextView.
This is not what is happening. First you create a new AddNumber activity.
public void addNumber(View view){
Intent intent = new Intent(this, AddNumber.class);
startActivity(intent); // This launches a new AddNumber Activity
}
And then here you are creating a new MainActivity instance.
public void addNumber(View view){
value = Integer.parseInt(numberEditText.getText().toString());
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("value", value);
startActivity(intent); // This launches a new MainActivity
}
So you're basically building a giant stack of MainActivity / AddNumber instances.
You need to start AddNumber with startActivityForResult and then handle that in MainActivity. Then you will be working with the original MainActivity and the original ViewModel and you will be able to update it.
Please refer to the documentation on starting an Activity for result.
Hope that helps!

Related

Pass int to another Activity

Before you flame me:
I know there are uncountable tutorials out there, and I know myself how to pass data to another ACtivity, just like that.
In my case that's diffrent tho. "Usually" data is passed to another activity through Intents, Bundles ecc and the other Activity is started.
Here's my case:
I have an Item with 4 parameters (Image, String,String, int)
In an AdapterClass I have a PopUpView which retakes those 4 parameters.
What I'd like to achieve is the following:
With the click of a button, the 4th parameter, the int should be sent to the Main activity and inserted in a textView inside the MainActivity, without (here's the main diffrence between this and the other questions)launching the Main Activity.
How can this be done?
TIA.
use BroadcastReceiver to send that 4th int to MainActivity
in PopupView do these:
Intent intent = new Intent("SOMEACTION");
intent.putExtra("4th_int", value);
activity.sendBroadcast(intent);'
//In MainActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IntentFilter filter = new IntentFilter("SOMEACTION");
this.registerReceiver(mReceiver , filter);
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(this.mReceiver );
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == "SOMEACTION") {
// retrieve the 4th int value and update something in MainActivity
}
}
};

Trouble understanding how intents work

I'm a noobie making a quiz in Android Studio and i'm trying to pass an integer between activities to add to the amount of questions they got correct for the end but in the second activity it isn't changing when I answer the first question correct.
Question1 activity:
public class Question1 extends AppCompatActivity {
public int correctAnswers = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question1);
Intent intent = new Intent(Question1.this, Question2.class);
Intent i = getIntent();
Intent answersCorrect = new Intent(Question1.this, Question2.class);
answersCorrect.putExtra("correctAnswers", correctAnswers);
}
public void submitQuestion1(View view) {
EditText question1TextInput = (EditText) findViewById(R.id.question1TextInput);
if (question1TextInput.getText().toString().length() >= 1) {
startActivity(new Intent(Question1.this, Question2.class));
if (question1TextInput.getText().toString().toUpperCase().contentEquals("FATHER")) {
correctAnswers += 1;
Intent answersCorrect = new Intent(Question1.this, Question2.class);
answersCorrect.putExtra("correctAnswers", correctAnswers);
}
}
}
}
Question2 Activity:
public class Question2 extends AppCompatActivity {
public int correctAnswers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question2);
Intent intent = getIntent();
int number = intent.getIntExtra("correctAnswers", 0);
TextView myAwesomeTextView = (TextView)findViewById(R.id.text);
myAwesomeTextView.setText(String.valueOf(number));
}
}
you duplicate your intent here:
Intent intent = new Intent(Question1.this, Question2.class);
Intent i = getIntent();
Intent answersCorrect = new Intent(Question1.this, Question2.class);
answersCorrect.putExtra("correctAnswers", correctAnswers);
replace it to:
Intent intent = new Intent(Question1.this, Question2.class);
intent.putExtra("correctAnswers", correctAnswers);
startActivity(intent);
in your second Activity:
int correctAnswers;
correctAnswers = (int) getIntent().getIntExtra("correctAnswers", 0);
So basically, when you have one activity and want to open a second activity, an Intent is the most important thing to have. It's responsible for communcation between your system and your application.
Intent is responsible for starting an activity, starting a service, and delivering a broadcast.
Note that there are two different types of intent: Explicit and Implicit.
Explicit Intent is used in this manner:
You have Activity_1 and you KNOW that you want to start Acticity_2 FROM Activity_1.
Implicit Intent is used when you DON'T know the name of the activity that you want to start.
Now, I know you probably understand what the StartActivity() method DOES, but StartActivity always requires an intent to go into the parenthesis. StartActivity(Activity_2); will not work.
So, when using Explicit Intent:
Intent i = new Intent(Activity_1.this, Activity_2.class);
StartActivity(i);
You start with making a reference - i - and, inside the parameters, the first being the activity from which you are calling the second activity, and the second being the activity which you want to call.
Here's a video on Intents as well: https://youtu.be/FH1Ym1KjJNc
Hope this helped.
Move the intent to a field. You only need it once.
Then, the issue is that you start the other activity too soon, without setting any value. You started the other activity with an empty, new Intent
public class Question1 extends AppCompatActivity {
public int correctAnswers = 0;
final Intent answersIntent = new Intent(Question1.this, Question2.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question1);
}
public void submitQuestion1(View view) {
EditText question1TextInput = (EditText) findViewById(R.id.question1TextInput);
String answer = question1TextInput.getText().toString();
// No need to check for length if directly checking another string
if (answer.toUpperCase().contentEquals("FATHER")) {
answersIntent.putExtra("correctAnswers", ++correctAnswers);
startActivity(answersIntent);
}
}
If you plan on sharing that value over many questions, try SharedPreferences.
FWIW, make a generic View for any question that has the question text and possible answer fields. Try not to make one activity per question.

Using activity objects in Intents

(I'm unsure if I am doing this correctly.)
I am creating a simple timetable app which has a main timetable activity with five buttons to five different days. When a button is clicked I want to start an activity that uses a base activity that takes in two int arrays which are just the codes of lessons to pass to a data class. How do I use this base class to create multiple different activities using intents when a button is clicked?
Timetable Activity (Simplified)-intent code not working.
public class TimetableActivity extends Activity {
private Button monABut;
int[] monAlessons = {5,2,6,5,5};
int[] monAteachers = {0,2,7,1,0};
public DayAOneActivity mondayA = new DayAOneActivity(monAlessons,monAteachers);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timetable);
monABut = (Button) findViewById(R.id.monAButton);
monABut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(),mondayA);
startActivity(i);
}
});
}}
Day activity constructor
public class DayAOneActivity extends Activity {
int[] lessonCodes;
int[] teacherCodes;
public DayAOneActivity(int[] lessonCode, int[] teacherCode){
this.lessonCodes = lessonCode;
this.teacherCodes = teacherCode;
}
The correct way to start activity is to use it's class:
Intent i = new Intent(TimetableActivity.this, DayAOneActivity.class);
startActivity(i);
Activity object itself is created by Android framework automatically

Returning back to main activity from gameover screen

Hi so even though I have seen a couple of topics about linking activities or returning I can not get my return back to activity to work. I abit of back ground the the app when the user gets an answer wrong or runs out of time it goes to game over taking the score across with it and displaying it on the game over, here's the working code for that if it helps solve my issue:
Main Class:
public void fail(){
{
Intent myIntent = new Intent(MainActivity.this,gameover.class);
myIntent.putExtra("number", score);
MainActivity.this.startActivity(myIntent);
finish();
}
gameover class:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameover);
re_run = (Button) findViewById(R.id.retry);
EndScore = (TextView) findViewById(R.id.show);
int getVal;
getVal = getIntent().getExtras().getInt("number");
String s = String.valueOf( getVal );
EndScore.setText(s);
}
Now the reason I shared the above working code because I have the feeling the intent that takes the user and score to the gameover screen, is messing with the retry/return code as shown below:
private void setButtonOnClickListeners(){
re_run.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
Intent retry = new Intent(getApplicationContext(),
MainActivity.class);
startActivity(retry);
}
});
}
From what I can find from those topics these seems to be the correct method. but when the code is run the re_run button does nothing. Any help?
You use "setButtonOnClickListeners()" to implement setOnClickListener and so override the onClick. But when did you call setButtonOnClickListeners?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameover); re_run = (Button)
findViewById(R.id.retry);
EndScore = (TextView) findViewById(R.id.show);
int getVal;
getVal = getIntent().getExtras().getInt("number");
String s = String.valueOf( getVal );
EndScore.setText(s);
setButtonOnClickListeners();
}
You can maybe check that your OnClick is working correctly adding a log line in LogCat. Log.d("GameOver", "Retry onclick ok");
You are finding a view before it was inflated (R.id.retry).
Change the sequence of commands to:
super.onCreate(savedInstanceState);
setContentView(R.layout.gameover);
re_run = (Button) findViewById(R.id.retry);
Also try changing the intent to:
Intent retry = new Intent(GameOver.this, MainActivity.class);
retry.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
I personally used startActivityForResult(Intent) to start the game over screen, and once the player inputted his name or pressed something or quit the activity with Back, then it returned a value to onActivityResult(..) in which I called finish().
EDIT:
Game ends, so I started activity using
Intent i = new Intent();
i.putExtra("Score", scoreCount);
i.setClass(context, HighScoreInputActivity.class);
context.startActivityForResult(i, 0);
Then when you insert the scores and stuff, you close the game screen in GameActivity with
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
this.finish();
}

Buttons isn't setting value

Im brand new to android and I have no idea what I'm doing wrong. The current code looks like:
public class TypeActivity extends Activity {
private boolean alcoholin = false;
...
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.search_type);
alcohol = (Button) findViewById(R.id.alcohol_button);
...
alcohol.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
alcoholin=true;
Intent i = new Intent (TypeActivity.this,ingredients.class);
startActivity(i);
}
});
...
public boolean getalcholin(){
return alcoholin;
}
This code is then supposed to set a value in another class. I have tested the code and I know that if i state the the boolean is true in the beginning of my code, then I will make the other code's boolean equal true. However, if I try to set the value when the user presses the button the value does not get updated.
Please help!
On Android the standard way to send data from one Activity to another is by specifying "extras" on the Intent that you use to start a new activity.
You are already using an Intent in your onClick method to start your "ingredients" activity (Your code would be more readable if you named your activity something like IngredientsActivity instead) - you just need to add some "extras" to it.
Please read up on the training tutorial here, but without knowing what your ultimate goal is you probably want something like:
alcohol.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent (TypeActivity.this,IngredientsActivity.class);
i.putExtra(IngredientsActivity.EXTRA_INGREDIENT_TYPE, "alcohol");
startActivity(i);
}
});
... and then in IngredientsActivity you would have something like:
public static final String EXTRA_INGREDIENT_TYPE = "ingredient";
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ingredients);
String ingredientType = getIntent().getStringExtra(IngredientsActivity.EXTRA_INGREDIENT_TYPE);
}
This would never work because alcoholin would NOT exist as this is an entirely different Activity. Why don't you instead use the Extras of the intent to pass data between the two Activities.
Standards
Class names should always have each word capitalized like MyClassObject in java.

Categories