Saving high score on android

Hello,

I’m finalizing my first game for Android. It is not a big revolution but I decided to start with a small project in order to learn about JME. Now, I would like to save the high score and other parameters on the mobile device. What is the recommended approach? I’ve been looking around the Savable interface and the BinaryExporter/Importer, but I cannot figure out how to use them on an Android platform and I’m not sure this is the technique recommended for android.

Thanks for your help

My approach is basic and simple works so far on all android devices I have tested.
It also works in all other OS’s.(Windows/Linux/etc.)
GameData.java
[java]
/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package za.co.tgiantlab.common.save;

import java.io.Serializable;
import java.util.Properties;

/**
*

  • @author NideBruyn
    */
    public class GameData implements Serializable {

    private String playerName;
    private String gameName;
    private int score = 0;
    private int level = 0;
    private int completedLevel = 1;
    private boolean soundOn = true;
    private boolean fxOn = true;
    private boolean debugOn = false;
    private Properties properties = new Properties();

    public boolean isDebugOn() {
    return debugOn;
    }

    public void setDebugOn(boolean debugOn) {
    this.debugOn = debugOn;
    }

    public String getPlayerName() {
    return playerName;
    }

    public void setPlayerName(String playerName) {
    this.playerName = playerName;
    }

    public Properties getProperties() {
    return properties;
    }

    public void setProperties(Properties properties) {
    this.properties = properties;
    }

    public int getScore() {
    return score;
    }

    public void setScore(int score) {
    this.score = score;
    }

    public boolean isSoundOn() {
    return soundOn;
    }

    public void setSoundOn(boolean soundOn) {
    this.soundOn = soundOn;
    }

    public boolean isFxOn() {
    return fxOn;
    }

    public void setFxOn(boolean fxOn) {
    this.fxOn = fxOn;
    }

    public int getLevel() {
    return level;
    }

    public void setLevel(int level) {
    this.level = level;
    }

    public int getCompletedLevel() {
    return completedLevel;
    }

    public void setCompletedLevel(int completedLevel) {
    this.completedLevel = completedLevel;
    }

    public String getGameName() {
    return gameName;
    }

    public void setGameName(String gameName) {
    this.gameName = gameName;
    }

}

[/java]

and then the service which is called to save the GameData.
GameSaves.java

[java]

/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package za.co.tgiantlab.common.save;

import com.jme3.system.JmeSystem;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.logging.Logger;

/**
*

  • @author NideBruyn
    */
    public class GameSaves {

    private File file;
    private String fileName = “defaultgame.save”;
    private GameData gameData;

    public GameSaves(String fileName) {
    this.fileName = fileName;
    }

    public GameData getGameData() {
    return gameData;
    }

    public void setGameData(GameData gameData) {
    this.gameData = gameData;
    }

    /**

    • Read any saved data from the file system.
      */
      public void read() {
      File folder = JmeSystem.getStorageFolder();

      if (folder != null && folder.exists()) {
      try {
      file = new File(folder.getAbsolutePath() + File.separator + fileName);
      if (file.exists()) {
      FileInputStream fileIn = new FileInputStream(file);
      ObjectInputStream in = new ObjectInputStream(fileIn);
      try {
      gameData = (GameData)in.readObject();

               } catch (ClassNotFoundException ex) {
                   Logger.getLogger(GameSaves.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
               }
      
           } else {
               file.createNewFile();
               gameData = new GameData();
               save();
           }
      
       } catch (IOException ex) {
           Logger.getLogger(GameSaves.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
       }
      

      } else {
      }
      }

    /**

    • Write game data to the file system.
      */
      public void save() {
      File folder = JmeSystem.getStorageFolder();

      if (folder != null && folder.exists()) {
      if (file != null) {
      FileOutputStream fileOut = null;
      ObjectOutputStream out = null;
      try {
      fileOut = new FileOutputStream(file);
      out = new ObjectOutputStream(fileOut);
      out.writeObject(gameData);

           } catch (FileNotFoundException ex) {
               Logger.getLogger(GameSaves.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
      
           } catch (IOException ex) {
               Logger.getLogger(GameSaves.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
      
           } finally {
               if (fileOut != null) {
                   try {
                       fileOut.close();
                   } catch (IOException ex) {
                       Logger.getLogger(GameSaves.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
                   }
               }
      
      
           }
      
       }
      

      }
      }

}

[/java]

1 Like

Thanks for your support… I’ll try this immediately

No problem. A fellow jME programmer I can always help.

100% effective and easy! Thank you very much!

Great, enjoy!
:stuck_out_tongue_winking_eye:

You know we have a built in system in JME that does the same?
I use it for my android game and it works like a charm.
The thing is using the built in system you’ll have the same code on desktop and android.
Your GameData just have ti implement the Savable interface.
Than you have a SaveGame class with static methods like saveGame, loadGame and so on.
You also have to add a permission in your manifest

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

If you keep in your idea to use the Serializable approach, then you should add a serialVersionUID id.

http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

I let you read the last paragraph of the javadoc, but basically it’s because without an explicit declaration of it, it will be performed at runtime and could lead to some exception only because you made small change in your class, (maybe like changing the order of field declaration but this is an assumption).

Anyway, it’s strongly recommended to add it, so … yeah, you should add it.

This was purpose of my initial question: I wanted to star using the Savable class, but I was not sure to start with the best approach for android. Now I know Savable works with android too, I’ll try it!
The main issue I had to face was to find where to store the data… The code provided by ndebruyn was very helpful for that!

@dcaso said: This was purpose of my initial question: I wanted to star using the Savable class, but I was not sure to start with the best approach for android. Now I know Savable works with android too, I'll try it! The main issue I had to face was to find where to store the data... The code provided by ndebruyn was very helpful for that!

SaveGame already does that.
http://hub.jmonkeyengine.org/javadoc/jme3tools/savegame/SaveGame.html

Absolutely… I have to improve the way I’m looking for information… SaveGame does everything I need with just on single line of code!