1

This might be a stupid question, and this might also be a duplicate. But, I really do not know and have not been able to find the solution to it, at all. My question is, how do apps save data. I'm making an app with LibGDX and Java for Android devices, and am just stuck pondering on this. How is it that, for example, when I close down Candy Crush and reopen it the day after, it remembers where I'm at even though the app resets? If this does happen to be a duplicate, I would strongly appreciate the other forum, and apologize for duplicating. I just haven't been able to find one. Thanks in advance!

miketreacy
  • 1,120
  • 1
  • 11
  • 17
  • 3
    It exist dozens of ways to do that... from Candy Crush... it's simple "Web Services" they "remember" the state by passing the data from server to app. Other ways is by using SharedPreference or using a directory folder to save data on the SD Card. SQL is other option. The point is... there is non an unique way, the best way to save data is the one that works for you. – Mariano Zorrilla Sep 17 '15 at 02:24
  • have you ever played any games on your computer. How comes the game remembers what level you are at and what score you have. Why should Android Java or Native Java be any different and not be able to store data either remotely or on the device and retrieve it when the app starts. Its not magic, its just a programming language just like any other. – Tasos Sep 17 '15 at 02:45

4 Answers4

1

A lot of Games have different approaches to this depending on their requirements. Games like: Candy Crush, Age of War or Clash of Clans, have all user information stored in an online database. The user information is fetched on startup from said database. You could then Store that information locally so it loads faster. Then next time you launch your app, you load the data locally, and if you cant, load it from the server again. You can push new information to the server every time you want to save the game state. It is difficult to give you a specific answer without knowing what kind of game you are making.

You should read through this post: Which Android Data Storage Technique to use? It has a lot of information for saving data on android.

Sync data between Android App and webserver Is yet another good post to read through. It gives you some information on how to sync the data you have saved locally and on the web server.

Google cloud storage is also another option: https://cloud.google.com/solutions/mobile/how-to-build-mobile-app-with-app-engine-backend-tutorial/

Google also offers a Saved Game Service: https://developers.google.com/games/services/common/concepts/savedgames?hl=en

If however you are just making a Basic Game. I recommend that you use a local data base in combination with Shared Preferences.

If you only store data locally, there is a potential for getting "Hacked". If you have the data on the server and locally, you can "handshake" and check if the data is correct.

Community
  • 1
  • 1
1

This is a broad question but I try to cover a view elements on the topic. Candy Crush Sage resets itself if you do not register or associate your account with something like Facebook and reinstall the app. They most likely use a database to store things in. If you are not registered things might just be stored locally.

LibGDX offers a handy feature to store data locally. It's called Preferences and you simply write to it and the next time you open your app it persists.

Preferences pref = Gdx.app.getPreferences("somefile");
pref.putString("name", "Menyo");
pref.putInteger("level", 20);

However when you uninstall this data goes with it and it's neither very secure for players that like to "investigate". Other then that you can store your own created data in some place. If you store it outside the internal app it persists even after deleting the app and as long the data stays and your app looks in the same location after a reinstall you should be able to retrieve the data. But as you might expect this is not fail-proof either.

The only real way to make sure is to have somekind of login mechanism. The most viable way is a database. I have a similar system running now but there is a server in between the client and the database. You can store any data in the database and link it to the player by his ID.

  • New players can opt to play as a guest. This creates a new account with "Guest" + id as a name. When a player links it's account to something like Facebook or a email address the account will persist and so will the data linked to it.

  • Existing players will login when they install your app and you can store there login information on there device so they automatically login if that data exists and is valid.

To setup a database I strongly advice to never connect directly to the database through the clients device. Either have a webservice or like I am currently doing a KryoNet server. The reason here is that you need to sanitize data coming from clients. You could do this from a clients device but you do not have full control over a that. Do your sanitizing of user input always on the server side.

Creating a webservice to connect trough a database is pretty easy if you know a bit of PHP and mysql. All you need is sending a HttpRequest to that php page and let it do the work.

public class WebTest {
    HttpRequestBuilder builder;
    Net.HttpRequest request;

    public WebTest()
    {
        builder = new HttpRequestBuilder();
        request = builder.newRequest().method(Net.HttpMethods.GET).url("http://yourdomain.com/script.php").build();
        request.setHeader("Content-Type", "application/x-www-form-urlencoded");


        final long start = System.nanoTime();
        Gdx.net.sendHttpRequest(request, new Net.HttpResponseListener() {
            @Override
            public void handleHttpResponse(Net.HttpResponse httpResponse) {
                Gdx.app.log("Test", "HTTP Response code: " + httpResponse.getStatus().getStatusCode());
                Gdx.app.log("Test", "HTTP Response code: " + httpResponse.getResultAsString());
                Gdx.app.log("Test", "Response time: " + ((System.nanoTime() - start) / 1000000) + "ms");
            }

            @Override
            public void failed(Throwable t) {
                Gdx.app.log("Test", "HTTP request failed");
            }

            @Override
            public void cancelled() {
                Gdx.app.log("Test", "HTTP request cancelled");
            }
        });
    }
}

Put a php script called script.php in yourdomain.com and echo something out in it. Then this code should receive that echo inside your app.

You can also create xml and parse that with your favorite parser. But you have to set the header of the request to receive xml properly.

request.setHeader("Content-Type", "text/xml");

Here is a PHP MySQL connection that sends feedback in XML.

<?php
$link = mysqli_connect("127.0.0.1", "root", "", "chatapp");
$xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\" ?><mysql></mysql>");
if (!$link)
{
    $xml->addChild("error", "Error: Unable to connect to MySQL.");
    $xml->addChild("error", "Debugging errno: " . mysqli_connect_errno());
    $xml->addChild("error", "Debugging error: " . mysqli_connect_error());
    exit;
}

$xml->addChild("success", "Success: A proper connection to MySQL was made!");
$xml->addChild("success", "Host information: " . mysqli_get_host_info($link));

//Sends the xml to whoever requested this
print($xml->asXML());

mysqli_close($link);
?>

Now you can simply use PHP to login a user into the database like you would do with a regular web page. There are plenty of php tutorials that cover this subject. Of course you can use any server side scripting for this.

Your own server to connect to a database is possible too but requires a lot more work. But KryoNet takes a lot of work from you. Your own server does mean you can store data on the server and exchange those very fast through a TCP or UDP connection. You basically have much more control over what is being exchanged.

Madmenyo
  • 8,389
  • 7
  • 52
  • 99
  • Personally i use Realm on the Android side. It's an ORM which makes life very simple. https://realm.io/ you could also use java serialization to store and ecnrypt objects. I just wanted to offer some alternative suggestions to the mix. Although serialization is not overly recommended it's interesting as a choice. http://developer.android.com/reference/java/io/Serializable.html – Jesson Atherton Sep 17 '15 at 13:35
0

There are a lot of ways to do this.

For some online application, they used network connection to communication with their servers such as online MYSQL servers, Webservices, and so on.

For offline application, SQLite, SharedPreferences, Internal and External Storage are used.

http://developer.android.com/guide/topics/data/data-storage.html

cw fei
  • 1,534
  • 1
  • 15
  • 33
0

It depends on what you want to be saved. There are many ways to save things like others have mentioned. If you want to save just a single variable to the device using a pref would probably be your best bet.


Here is how you could use a pref.

//This is how you can store a boolean, using a pref
SharedPreferences prefs = getSharedPreferences("BOOL", MODE_PRIVATE);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putBoolean("ads", showAds);
        editor.commit();

`//showAds is a boolean that you are storing

you can make a function to retrieve a stored boolean like this

public boolean checkStoredBool(){
        SharedPreferences prefs = getSharedPreferences("BOOL", MODE_PRIVATE);
        boolean extractedBool = prefs.getBoolean("ads", false);
        return extractedBool;
    }

//The false in the previous code, is what would be called in if no value was stored

You want to make sure when creating the SharedPreferences the part in quotes matches what you put in the codes when you stored the boolean.

Also when calling prefs.getBoolean the part in the quotes needs to match what was in the quotes when you used editor.putBoolean earlier


Now in your code if you want to call in the saved code you simply just call the method.

For example if you want to have an if statement that checked if the stored value was true or false it would look something like this

if(checkStoredBool() == true){
    //code when it's true
}
else{
    //code when it's false
}
  • I'm going to make a game with different levels and unlocked level select items, achievements, points total, etc. So a series of variables and arrays. – Shivashriganesh Mahato Sep 19 '15 at 06:02
  • 1
    I added some more detail on how you could use prefs. Let me know if this helps. I know its a little late. Or extremely late. – Josiah Lauby Feb 13 '17 at 01:09