1

I am making a simple game that uses GridView and a custom Adapter. It is basically a game that player can move through the GridView (simply changing the images of cells). The game has 10 levels. Problem is, when I get out of the activity (e.g. going back to the MainActivity) the game is reset. Also naturally when phone is turend off and on the game is reset.

I want to preserve the game state so when the player enters the GameActivity, he/she can continue with the game.

I only require 3 things to be saved, the Adapter, number of Level and the available moves. Simply if I knew how to work this out I could achieve what I need:

public class GameState implements Serializable {

    private GameAssetAdapter mAdapter;
    private int mLevel;
    private int mAvailableMoves;

    public GameState(GameAssetAdapter adapter, int level, int availableMoves) {
        mAdapter = adapter;
        mLevel = level;
        mAvailableMoves = availableMoves;
    }

    public GameAssetAdapter getAdapter() {
        return mAdapter;
    }

    public int getLevel() {
        return mLevel;
    }

    public int getAvailableMoves() {
        return mAvailableMoves;
    }
}

So the question is, how can I save this object to internal storage and retrive it back when necessary?

I already have tried the onSaveInstanceState but it does not work as expected. phone off/on will reset this. Even if user wipes the app in the app list of android it will be reset. What should I do?

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable(AppConstants.GAME_SAVE_ASSET_ADAPTER, mGameAssetAdapter);
}

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

    if(savedInstanceState != null)
    {   //Restore mGameAssetAdapter if was saved perviously
        if(mGameAssetAdapter == null){
            restoreGameAssetAdapter(savedInstanceState);
        }
    }

    //TODO get level and states!!
    mGameGridView = (GameGridView)findViewById(R.id.game_grid_view);
    mGameGridView.setNumColumns(GameConstants.COLUMNS);
    mGameGridView.setColumnWidth(GameHelper.getOptimumAssetImageWidth(this,
            GameConstants.COLUMNS));
    if(mGameAssetAdapter == null) {
        mGameAssetAdapter = new GameAssetAdapter(this, mLevel);
    }
    mGameGridView.setAdapter(mGameAssetAdapter);
    this.setTitle("Snakes and Ladders - Level " + mLevel);

    setupEvents();
}

private void restoreGameAssetAdapter(Bundle savedInstanceState) {
    if(savedInstanceState.getSerializable("GAME_ASSET_ADAPTER") != null){
        mGameAssetAdapter =
                (GameAssetAdapter) savedInstanceState.
                        getSerializable("GAME_ASSET_ADAPTER");
        Log.v(TAG, "Restored saved GameAssetAdapter! Hoooray!");
    }
}
Dumbo
  • 13,555
  • 54
  • 184
  • 288

1 Answers1

1

You can just write the state to storage. Here is some code from my personal stash:

private static byte[] readBytes(String dir, Context context) throws IOException
{
    FileInputStream fileIn = null;
    DataInputStream in = null;

    byte[] buffer = null;

    fileIn = context.openFileInput(dir);
    in = new DataInputStream(fileIn);

    int length = in.readInt();

    buffer = new byte[length];

    for(int x = 0;x < buffer.length;x++)
        buffer[x] = in.readByte();

    try 
    {
        fileIn.close();
    } catch (Exception e) {}

    try 
    {
        in.close();
    } catch (Exception e) {}

    fileIn = null;
    in = null;

    return buffer;
}

private static void writeBytes(String dir, byte bytes[], Context context) throws IOException
{
    FileOutputStream fileOut = null;
    DataOutputStream out = null;

    fileOut = context.openFileOutput(dir, Context.MODE_PRIVATE);
    out = new DataOutputStream(fileOut);

    int length = bytes.length;

    out.writeInt(length);
    out.write(bytes);
    out.flush();

    try 
    {
        fileOut.close();
    } catch (Exception e) {}

    try 
    {
        out.close();
    } catch (Exception e) {}
}

You can save your state by using the writeBytes() method, then when the app is relaunched, all you have to do is use readBytes() to restore the game state.

If I may make one small structural suggestion, I like to make a 'package' class that holds my state variables when I write it to disk like this:

public class SavedState implements Serializible
{
    public GameState state;
    int id;
    ...
}

Then when you write this to disk, you will have all of your state variables in one clean class. I would also recommend not saving your DisplayAdapter for your list view (you might have a lot of problems) or whatever it is. Save the underlying data structure to this package class and then create a new DisplayAdapter when you resume the app state.

If you don't know how to turn an object into a byte array, here is the SO question for it:

Community
  • 1
  • 1
John
  • 3,769
  • 6
  • 30
  • 49