A task. Saving CheatActivity

I can save the status of CheatActivity. Help me please! Here is my code. What am I doing wrong?

package com.bignerdranch.android.geoquiz;

import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class CheatActivity extends AppCompatActivity {
private static final String EXTRA_ANSWER_IS_TRUE =
“com.bignerdranch.android.geoquiz.answer_is_true”;
private static final String EXTRA_ANSWER_IS_SHOW =
“com.bignerdranch.android.geoquiz.answer_is_true”;
private static final String TAG = “CheatActivity”;
private boolean mAnswerIsTrue;
private int mAnswerShow = 0;
private TextView mAnswerTextView;
private Button mShowAnswerButton;

public static Intent newIntent(Context packageContext, boolean answerIsTrue) {
    Intent intent = new Intent(packageContext, CheatActivity.class);
    intent.putExtra(EXTRA_ANSWER_IS_TRUE, answerIsTrue);
    return intent;
}
public static boolean wasAnswerShow (Intent result) {
    return result.getBooleanExtra(EXTRA_ANSWER_IS_SHOW, false);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_cheat);

    if (savedInstanceState !=null) {
        mAnswerShow = savedInstanceState.getInt("mAnswershow");
        mAnswerIsTrue = savedInstanceState.getBoolean("mAnswerIsTrue");
    }

    mAnswerIsTrue = getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE, false);
    mAnswerTextView = (TextView) findViewById(R.id.answer_text_view);
    mShowAnswerButton = (Button) findViewById(R.id.show_answer_button);
    mShowAnswerButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mAnswerIsTrue) {
                mAnswerTextView.setText(R.string.true_button);
            } else {
                mAnswerTextView.setText(R.string.false_button);
            }
            setAnswerShowResult(true);
        }
    });
}

private void setAnswerShowResult (boolean isAnswerShow) {
    Intent data = new Intent();
    data.putExtra(EXTRA_ANSWER_IS_SHOW, isAnswerShow);
    setResult(RESULT_OK, data);
}

@Override
public void onStart() {
    super.onStart();
    Log.d(TAG, "onStart() called");
}

@Override
public void onResume() {
    super.onResume();
    Log.d(TAG, "onResume() called");
}

@Override
public  void onPause() {
    super.onPause();
    Log.d(TAG, "onPause() called");
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putInt("mAnswershow", mAnswerShow);
    outState.putBoolean("mAnswerIsTrue", mAnswerIsTrue);
}

@Override
public  void onStop() {
    super.onStop();
    Log.d(TAG, "onStop() called");
}
@Override
public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy() called");
}

}

I think the error is in this function. If you call the super.onSaveInstanceState(outState) after setting the extra data on the outState, then you should be good to go.

The reason why I think this is the error, is that the super class is probably also handling the logic of actually saving the Bundle. Therefor sending the bundle to the super class before setting extra data, makes setting the extra data pointless, cause it never gets saved :slight_smile:

Your mAnswerShow field is saved correctly in onSaveInstanceState, and restored correctly in onCreate. However, it is never assigned or accessed outside of these two lines, so it is completely useless.

To make this field meaningful, you should assign mAnswerShow somewhere, probably in setAnswerShowResult. After restoring the state, you will need to call setResult again (possibly via setAnswerShowResult) in order to send the result back to the calling activity.

It seems indeed that the mAnswerShow isn’t being used anywhere else. But I assumed his problem was with the rotating of the screen and therefor recreating the screen. Atleast, that’s why you would use the onSaveInstanceState in this case. The other value he saves in the bundle, does get used.
For me, it resolved the problem of calling the super after assigning the values to the bundle. But if saving the state for rotating the screen isn’t his problem, then I tried to answer a question which wasn’t asked, my apologies for the confusion it could’ve created :slight_smile:

Thank you! You can show how to make the saving of the activity after the screen rotation on the example of my code? The example from the book is understandable, for example, to preserve the value of the index of the question. In the assignment, I can not understand what I should save.

I would place the super.onSaveInstanceState(outState) as the last line in this function. So it would be like this:

@Override
protected void onSaveInstanceState(Bundle outState) {

outState.putInt("mAnswershow", mAnswerShow);
outState.putBoolean("mAnswerIsTrue", mAnswerIsTrue);`

super.onSaveInstanceState(outState);`

}

The reason why you want to save the state is because you want to know if somebody already cheated by clicking on the button to show the answer. If you don’t save the state, people using your app can cheat by clicking to show the answer and then turn the phone to remove the value that keeps track of them cheating. That way they can cheat the cheat system and cheat even more :slight_smile:

It doesn’t matter when you call super.onSaveInstanceState, as long as you do that somewhere in onSaveInstanceState. While the superclass does handle actually saving the Bundle, this does not occur in onSaveInstanceState.

The problem is that the field mAnswerShow will always be 0, whether the user cheated or not. To fix this, you first need to assign this field in setAnswerShowResult:

private void setAnswerShowResult (boolean isAnswerShow) {
    mAnswerShow = isAnswerShow ? 1 : 0; // add this line somewhere in this method
    Intent data = new Intent();
    data.putExtra(EXTRA_ANSWER_IS_SHOW, isAnswerShow);
    setResult(RESULT_OK, data);
}

This will save whether the user cheated, but this fact won’t be sent back to the calling activity without further effort. To accomplish this, you can set the result again when you restore the Activity’s state.

    if (savedInstanceState !=null) {
        mAnswerShow = savedInstanceState.getInt("mAnswershow");
        setAnswerShowResult(mAnswerShow != 0); // add this line
        mAnswerIsTrue = savedInstanceState.getBoolean("mAnswerIsTrue");
    }

I also recommend making mAnswerShow a boolean instead of an int, since that more accurately describes that field’s role.

Depending on how your QuizActivity is implemented, a cheater may still be able to win by cheating, returning to QuizActivity, starting CheatActivity again, rotating the device, and returning to QuizActivity without cheating.

It seems indeed that it doesn’t matter when you call the super function. My apologies for the confusion it created. Just tested it out again and it does work. Before I had some issues getting it to work, so looked up some examples. In the examples everyone is calling the super function as last and for me it would make alot more sense calling it then, so I adopted the same habit.