• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

SOLVED Android App Doesn't Keep Save Data

hughrock18

Member
GMS2 - Android

My app is extremely simple.

It works by building and filling a ds_map. Only 50 boolean entries are stored in this map at any given time. You press the "save" button, and it is SUPPOSED to store said ds_map to a root ds_list (which is then stored to a wrapper ds_map, json_encoded, and then saved to its own file, "save.dat").

After that, the app (without closing it) has no problem using the "load" button to recreate the ds_map.

However, when the app IS closed and reopened, the file no longer exists.

There is absolutely NO code that erases the file. There is no "file_delete" function call anywhere (nor has there ever been) in this app.

Any help or direction would be greatly appreciated.
 

TailBit

Member
Note that the file isn't created unless you close it, untill that happens it pretty much only exists in a build-in buffer.

But that is just a shot in the dark, some code would be nice.
 

hughrock18

Member
Note that the file isn't created unless you close it, untill that happens it pretty much only exists in a build-in buffer.

But that is just a shot in the dark, some code would be nice.
I built a simple function to handle saving, and a separate one for loading (below). They are as follows:

GML:
// io_save_map_to_file();

var _ds = argument[0];
var _fn = argument[1];

var _file, _json;
var _wrapper = ds_map_create();
var _root = ds_list_create();

_root[| 0] = ds_map_create();
ds_map_copy( _root[| 0], _ds );
ds_list_mark_as_map( _root, 0 );
ds_map_add_list( _wrapper, "root", _root );

_json = json_encode( _wrapper );

_file = file_text_open_write( _fn );
file_text_write_string( _file, _json );
file_text_close( _file );

ds_map_destroy( _wrapper );
GML:
// io_load_file_to_map();

var _fn = argument[0];
var _ds = argument[1];

var _file, _json;
var _wrapper = ds_map_create();
var _root = ds_list_create();
var _map = ds_map_create();

_file = file_text_open_read( _fn );
_json = file_text_read_string( _file );
file_text_close( _file );

_wrapper = json_decode( _json );
_root = _wrapper[? "root"];
_map = _root[| 0];

ds_map_copy( _ds, _map );

ds_map_destroy( _wrapper );
The first is obviously for saving any ds_map to a file and the second is for loading a json encoded string from a file to a ds_map. A save button calls the "io_save_map_to_file()" function in its gesture-tap event. It even creates a rapidly fading window confirming the data was saved. A load button calls the "io_load_file_to_map()" (also in gesture-tap event) with the same confirmation window that will only show after the initial function is complete. These confirmation windows and the save/load functions are the ONLY code for the tap events here. It seemed so straight forward. Where am i messing things up?

Disclaimer: I know that there are other ways to store such simplistic data (ini for example). However, this has been regarded as the most stable method to saving data in GM (not 100% as to why). Regardless, i've seen several others make it work and it worked beautifully for them! I want this save method to work for the sake of more complex games (with more complex save structures).

EDIT: Almost forgot... the ds_map in question is loaded with 50 boolean values. Each one has a corresponding "light" that changes color depending on its respective boolean. I even set these to check every step. Slow i know, but it shows that the ds_map is filling up the way I intended it to. It's the only ds_map in the app and it is set as a globalvar at runtime. So referencing it anywhere should always reference the one and only map in the game (i imagine some sort of crashing error would have appeared if the app tried to save a non-existent ds_map).
 
Last edited:

Nocturne

Friendly Tyrant
Forum Staff
Admin
How are you testing? Just running through the IDE? Creating and APK and pushing it to the device? Uploading to Google Play on a beta channel? Note that when building from the IDE, there IS a game option to delete all save data on every run, so that could be the issue? I suspect not, as you say you're closing and opening the app, not running it again and again, but just to make sure... Tbh, on opening and closing the app I can't see any reason why this would happen, but I would certainly test using a built APK and a version downloaded form the store too, to see if the issue persists with a built app or not. More to try and narrow the issue down to a specific set of circumstances.

I would also point out that there are a couple of issues with your code... you have some pretty major memory leaks for one, as you create a DS map then decode the JSON, which creates a new DS map, over-writing the empty one you create, which is then de-referenced and can't be destroyed. json_decode creates a DS map by default, so you don't need to create one to store it. The same for the _root DS list and the _map DS map. Creating all those DS is unnecessary as they will be created for you as part of the decoding... and I'm wondering if this may be related to the issue since GM will reusing DS indices and it's getting confused somewhere...
 

hughrock18

Member
@Nocturne - wow. Never knew that json_decode would rebuild all the data structures like that! Is that documented somewhere? If not, it really should be. Feels like a sort of important fact. Or maybe it's supposed to be obvious enough to obviate the need. Anyway, there's an option to delete save data on each run? Where is this function? I may have messed with it before (a long time ago when I first got gms2 and was a total newb to the IDE). I still find a stupid option I've ticked from time to time.

EDIT: sorry. I forgot to answer your initial question. The app is being tested as a complete apk installed on my device.
 

hughrock18

Member
@Nocturne - Well... the "Always do full install of APK" was checked. I don't even remember doing that. Is it ok that I also have the "Install on Package" option ticked?

Standby for test. I'm attempting build now...
 
Top