I try to create LUDO game and when user stop the game I want to save game state (Activity state).
I understood that I need to save state in method OnPause() but there are lots variables that I need to save and there are all changing in time so I am not sure that I can save state in that way.
So can I save the whole Activity and OnResume() method to restored it and just continue whith the game?
Thanks.
Don't know what you mean by changing in time. Are you saying your game progresses even while the player isn't playing? Normally, you would save only the minimum amount of information necessary to recreate the current state. For a board game, this could be the locations of each players' pieces, and whose turn it is.
If you really have so much game state that it would be unwieldy to save and restore, or the game has to progress while the Activity is closed, or recreating the state from static data is too difficult (all propositions I would probably dispute, but we can take it a given for the sake of discussion), then I would suggest you write it as a client-server app, where an Android Service runs the game engine and your Activity does all the visuals and user interaction.
I think you are looking for How to save an Android application's state.
The documentation also provides details on saving persistent state with onPause.
Related
I recently got into Android development and I'm a bit confused about how the savedInstanceState works. Let's say I was making a game and I want to save the player's score, would I be able to save it during onSavedInstanceState() to the savedInstanceState Bundle and always be able to retrieve the score from it no matter whether the device was shut off or the user just completely closed the app?
If your question is how much is Bundle object kept in mememory, that would be temporarily.
The data is held in memory until the application is alive or killed by the OS (lack of memory), in other words if you force close the app (shut down the device or close the app) onSaveInstanceState is not used.
However if you want to permanently store the data you would have to use SharedPreferences and SQLite database.
I'm not sure I fully understand you but let me answer you and then tell me if this what you mean
the savedInstanceState has nothing to do with the save game, the save game usually should be when a cretin event happens or sometimes you choose that
if the user closed the game by pressing the home button for example you will save the game automatically for him , you should do that by overriding one of the Activity methods, onPause() is your best bet, because you want to keep the save even if the user restarted his phone for example.
see this for activity life cycle:
http://developer.android.com/training/basics/activity-lifecycle/index.html
On the other hand, the savedInstanceState is a mechanism used by android to save the activity temporarily, if the user went back to the game directly before the activity completely gets killed by the OS, you can restore the state of the activity instead of loading the game from the beginning and going to the start menu.
this principle holds in general not just in game.
to summarize it: the savedInstanceState is a way to restore your activity form the memory before it gets killed rather than loading it again. and it's NOT a way to save data premenantlly on the device
if this is what you want, then you can ask about how to work with the savedInstanceState
I'm having an issue with an android app I'm writing that seems like it should be a common issue but I can't find any information on it.
I have a scoreboard activity in my app that just stores a grid of scores in textviews, it's the kind of thing that the user will update, then hit the back key and look at some other activities, then come back later to update it, leave again, etc...
The problem is that every time they leave and come back the whole activity gets reset, losing all their scores. I can't use saveInstanceState because it isn't called on back key pressed. I really don't know where to go from here except for saving thew hole grid in sharedpreferences, I feel like there has got to be a better way though
Any ideas?
In general, you need to save any state information in onPause(), and recover it in onResume().
I was under the impression that various state information is kept automatically when you close the App, and automatically restores itself when start it back up again (until Android removes the App from its memory to make space, calling onDestroy()).
If I were you, I would store the grid in SharedPreference. It really is the most reliable solution.
You can also use the details in this topic:
https://stackoverflow.com/a/151940/503508
May this help you
When the user presses the BACK button, your foreground activity is destroyed. That activity will be called with onPause(), onStop(), and onDestroy(). That activity object will then be garbage collected (unless you introduced a memory leak).
onSaveInstanceState() will be called periodically if there is a chance that the activity will be destroyed shortly but in a way where the user might be able to navigate back to it. The prominent case for this is during a configuration change, such as rotating the screen.
What you should be doing in onPause(), if anything, is persisting data using "sqlite, file saving and other persistance methods". Once onPause() is called, there are no guarantees that this activity will stick around, or that your entire process will stick around. Anything you value, therefore, should get written out to persistent storage.
The "state" for onSaveInstanceState() would be things that affect the activity's UI but are not part of the persistent data model. Much of this is handled for you automatically by Android's built-in implementation of that method (e.g., the text in an EditText), but you can add your own information to the Bundle if you wish. However, your instance state is not your data model, so anything you want to stick around needs to be written out to persistent storage.
I am developing an Android application consisting of over 10 activities. I have some state objects that I access in almost every activity and for this purpose these were implemented as global static variables in the MyApplication class.
I noticed that this approach is OK as long as the user is "in" the application. However, when he presses the home button and opens another apps and then goes back to my app through the "Recent activities" button, I see that the Android system resets the statics from the MyApplication so I have to deal with NullPointerExceptions. I know that this behaviour is caused by Android killing and recreating the application process.
I know that the best way to persist this kind of data is using SharedPreferences or SQLite, and I have no problem checking if MyState==null in the onCreate for and restoring it, but the problem is that I don't know when to properly store my state object (in prefs or database). I tried to override MyApplication's finalize() - no good, I saw that onLowMemory may not be called, I don't see how can I use onPause, OnStop and so on because I have so many activities that the serialization de-serialization would considerably slow down the app.
Any thoughts?
Thanks in advance!
It is better to not depend on the Application class unless you need to load some data, before anything else is started. Android can kill your process at any time to free resources, so your app should be able to handle this. Save all of your data in a snigleton class, and load it lazily -- check for null, and if so load on first access. It the state needs to be persistent, consider staving it file/shared prefs. If not, your app can probably live without it, so just make sure you check for null, etc.
Generally, you should persist state when activities become inactive -- onStop(), onPause(), but you can save as soon as it makes sense (e.g., the user has entered all required data). Spin off an AsyncTask to save data in the background and let the user continue their work.
Attempting to decide (for my application) what to save in onPause() and what to save in onSaveInstanceState(), I combed the entire SO for hints and clear guidelines.
If I understand correctly, onSaveInstanceState() is best for saving "runtime changes" or "current state" (whatever that means), while onPause() is best for saving "persistent state" (whatever that means).
I am still having difficulty deciding what in my application constitutes "persistent state" vs. "current state". For example, while user preferences are clearly persistent, do I need to save them in onPause() when they are always saved automatically by the Android UI framework when the user changes them?
Do class data members need to be saved in onSaveInstanceState()? Do I need to do that for every class in my application?
I am confused.
Can you bring real-world examples of what must be saved in onPause() and what must be saved in onSaveInstanceState()? Except for device configuration changes, that is.
--
Some new insights, after my question has been answered:
onSaveInstanceState's Bundle is not written to anything, and it's not persistent in any way.
onSaveInstanceState's Bundle data will only be held in memory until the application is closed.
You do not need to store user preferences in onPause because as you say, the framework does that for you.
To distinguish between persistent data vs state information, think of a text editor application.
Persistent data
Let's say the user has typed a couple words and then exits the app. The user didn't explicitly tell us to save that data to a file, but it sure would be nice to store that data away for when they come back. This is persistent data and you want to store it away in onPause().
State data
Similarly, say you have 2 tabs and a variable that tracks which tab is currently selected. This is state data that you'd store in onSaveInstanceState().
Gray matter
Finally imagine you have a class in the editor that keeps track of the number of characters and number of lines in the editor. This is state data, you could store it in onSaveInstanceState() or you can throw it away and simply recalculate it when you start up again. Whether you throw it away might depend on how long it takes to calculate, for instance if you could prevent a network request by storing data, do so.
Further thoughts
By playing with your app it should be obvious if there's an area where you failed to squirrel the right data away. Be sure to do things like hit the home button and then close out your app from the device manager. This will let you hit the corner cases where your app is shut down rather than just paused.
If your UI state is consistent across lifecycle events and your user data remains, good job.
Edit based on comment
I think there are 2 pieces of criteria here to determine when/what to save.
The first is quite subjective - Do you want to save data at all? There's truly nothing forcing you to save state or data. Will saving this information make for a better user experience? If you are writing an email and trying to copy/paste text from another app, losing your half typed email every time the app gets closed would be frustrating.
The second piece, determining what to save depends on whether you can reconstruct your UI state based on the data that you have. For instance, if you have saved text data then that must mean that the user was editing text. So now we know to switch to the edit text tab and fill in the saved text.
Generally speaking, if the desire is that you want to return the user to the same place they left off then you need to think about the state data required to get back to that point. Imagine a pristine loaded version of your app
what data needs to change to turn that into the last state the user
saw?
what data do you need to store to get back here?
This is really how android works, your activity is destroyed and recreated and it is your job to set the pieces in motion again (if you choose to do so).
Here is answer. You can save state in three different ways.
1) Subclassing app (not a good idea).
2) SharedPreferences (good for simple data, quick and reliable)
3) SQLite Database (More complex, also reliable).
Now to answer your question. There are really NO guarantees with android. At any time it can and may destroy your application without calling any particular function before it does so. So if there is data that is vital to save, the answer is save it as soon as you get it. There is usually not much advantage to saving something later, if you know you are going to need something save it immediately.
onSaveInstanceState() is just for saving temporary variables related to layout or orientation changes.
In summary persistent state/data (that should survive a crash), should be saved ASAP, don't wait for onPause(), because there are no guarantees. That's the reality.
The case I have is a game, where I want to save persistant data to a gameserver.
As this may take awhile, I find it not a good thing to try and save in onPause, but rather in onStop.
According to the tests I have done, onStop seem to be able to run in the background while onPause blocks, atleast that is the case when I press home (tested with a simple for 1 to 10m loop in onPause and onStop).
Can anyone confirm this blocking theory ?
onStop NEEDS Honeycomb up (api11+), because before that version you can get killed before onClose is called.
See here and look for killable in the table - If reality matches the documentation is another question :).
I'm not very sure how to preserve all the variables initialiazed on an OpenGL ES app for Android. My app is quite slow to initialize, and if I don't preserve the initialiazed variables, every time I turn off and on again the screen, or press the home key and return to the app, all of the initial operations start again, and this causes a slow return to the game, and it goes back to the first state of the game.
How can I preserve the app status to go back to it without having to initialize everything again if the app is put in background? Do I have to modify the onSaveInstanceState function?
Edit: What I want is that the app doesn't reload the context, and that returning to it doesn't last like if it were first initiated
You need to use onSaveInstanceState and onRestoreInstanceState to save and load the variables,
I think Saving Android Activity state using Save Instance State is what you need
I still do not really comprehend your question. Anyway: you will have no other choice, depending on what state is thrown away. As in my comment above, there are at least 3 types of state:
(Game) state that can be recreated from assets.
(Game) state that represents the current users view (see answer from #AndrewWilkinson)
The OpenGL context.
Have a look at an Activity's lifecycle. When the process is not kicked out of memory, states 1. and 2. are preserved, and you need not worry. Bad thing is, you cannot know, so you need to prepare the app from being kicked out of memory and later recreated. So you need to preserve state 2. at anytime.
For state 3.: On each call to GLSurfaceView.Renderer.onSurfaceCreated, you can be sure there is no OpenGL context anymore. You need to upload everything that is needed for displaying again. Setting the preserve flag might help, but you cannot be sure.
If loading takes too long, consider to show a simple pause screen that does not take too long loading and keeps the user happy. Consider doing stuff in a more lazy fashion, s.t. some content is loaded on-demand and not eagerly.