Some of the users of my application complain that sometimes (in a random way) the settings of my application are getting reverted to their default state (usually after a reboot of the phone). I never managed to reproduce the problem though. I am thinking it is due to the fact that in many places in my app I have a piece of code that calls the shared preferences editor and commits changes - Can it resolves in corrupting the shared preference file if I try to commit several changes to the same preference file at the same time? (Multi-thread application)
I am really lost. I tried to look in the web for hours to find a solution without a success.
If anyone has even an idea so I can start investigating, I would be grateful.
Thanks,
Amit Moran
I'd echo the other answers - that you need to avoid conflicts if you don't want to corrupt the file - and I'd go further to suggest that you're probably misuing SharedPreferences.
SPs are designed to store small pieces of information about your app - user settings like volume or whether music is playing or things like that.
SPs are NOT designed for storing data which changes often and/or large amounts of data and it's a bad idea to try to do this (for the reasons you've discovered and a few others).
Remember that SPs are really just an XML file - you're incurring the overhead of parsing and recreating that every time you change it too!
The idea of an App which updates SPs in more than one thread is a bit mad I think - you need a better way of managing and storing the data you're saving - it will pay-off for you in more than one way...
According to the SharedPreferences.Editor documentation:
Note that when two editors are modifying preferences at the same time, the last one to call commit wins.
From this I gather that multiple simultaneous commits will not wipe out your preferences, but it's possible that not all changes you are attempting to write will end up getting written if multiple Editor instances are being used simultaneously. To avoid this you could put all preference modifications in synchronized blocks or even use one synchronized static method for all preference writing.
I suggest you use a singleton to manage the preferences. Whether you do this by implementing a true java singleton, or by using Android's Application Context is up to you. (see this question for several good arguments for/against each)
For something like SharedPreferences, this is a good way to manage them especially for a multi-thread application. This will possibly eliminate some of the questioning of whether or not the commits are conflicting with each other. This may not be the whole problem, but it's somewhere to start.
I had a similar problem: my preferences had not been saved reliably. On some devices (in my case the XOOM-Tablet) data got sometimes lost and sometimes not. I've solved the problem by simply calling clear() on the editor before commiting new data.
Shared Preferences get lost after shutting down device or killing the app
I found I was losing a particular entry in SharedPreferences by opening the editor, doing a getString on it, and then committing without doing a putString on the entry first, even if there was no required change. Once I stubbed in a putString to save the value no matter what, the entry stopped vanishing after the commit.
Related
I want to write an android calculator app like the one on my android phone. It saves history for operations and by clicking a button it shows last operations. Now my question is what is the best way to save operations? Is it reasonable to save them to a file in internal storage or what?
There's some options..
1) Include a SQLite Database, as others mentioned. This makes storing lots of information really easy. You can find tutorials on how to include one properly in your project, and don't hvae to care for much more. You can then work with content providers to read and store data.
http://developer.android.com/guide/topics/providers/content-providers.html
2) SharedPreferences. If you just intend to store like the last, or the last 3 Operations, you can just use shared Preferences. This is way less overhead than adding a Database, if it is a small project, albeit you will have to keep your data structured yourself.
http://developer.android.com/reference/android/content/SharedPreferences.html
3) If you just want to store the users current session you can just Keep a Stack of the used operations. On undo, or however you call it, you would just pop the stack.
By implementing onSaveInstanceState and Parcelable you can make sure that no data is lost on rotation / low memory and such.
I personally would advise you without knowing more about your project to use plain java objects and storing the state. A calculater would in most cases not need persistent storage. If you really want to know what the user did 2 weeks ago, you should use a Database.
I would recommend you to use database(SQLite) for storing the data.
If you don't know more about SQLite in android have a look at these
tutorials.
I think database should be handy for history if more than one operations has to be stored else for one operation you can use shared preference.
I'd like to develop an app which need some data persistency. For some reason, I don't want to use database. And I'd like something similar to the shared preference. But only have one more requirement:
I hope my data can be persistent across installation. That means even the app uninstalled the data still be stored in Android system safely.
Are there any suggestions? Thanks
P.S.: In iOS, I use the keychain.It works perfectly.
The only solution I can think of to ensure non-removal on uninstallation is to write a file somewhere on the external storage. However this is (a) insecure (b) prone to other issues such as users deleting it.
If you are worried about persisting data on upgrades then using a database with a ContentProvider you can achieve this fairly easily. Shared Prefs are only really meant for a small number of small values/primitives.
There is also the option of storing something remotely, with a web service if it fits with whatever need you have to retain data when uninstalled/reinstalled.
The majority of questions like yours indicate an issue somewhere else in the way your application is architected, if you provide more detail people here may give you a better solution
The only way I can think of doing it is syncing the data with the cloud and restoring it if the user reinstalls the app. You may want to look at leveraging the BackupManager.
I know similar question to this one has been asked a numerous times, and surfing through SO I partially found an answer, but not complete, and android docs don't really help. Obviously I know how they work and have used shared preferences many times before, but I am wondering at what point ( how many ) is too much, I've read people had ~ 100KBS stored without any problem. Long story short --
Did someone actually had problems with too many data stored in shared preferences and what was problem, does data get deleted or?
** this is only a question out of curiosity, I already have my large values stored in SQL DB, just wondered what would be and if there would be any problems if someone for some reason stored everything in shared preferences
Since SharedPreferences are stored in an XML file, and therefore lacks the strong transaction support of SQLite, I would not recommend storing "100KBS" in SharedPreferences.
That being said, the lowest size limit that I am aware of will be your amount of free heap space, as SharedPreferences reads that entire XML file's contents into memory.
There is a limitations of SharedPreference data. In my case it throw a Memory Exception when SharedPreference data cross 1428.51-kb.
So its better to use SQLite database when you required huge data to store.
From reading your question I would think that you should not be using SharedPreferences, because (a) they are intended for storing much smaller amounts of data (hence the use of XML), and (b) there are many simple alternatives.
The only thing 'special' about SharedPreferences is the integration with the Preferences Activity for showing your preferences to the user, and that is probably not applicable in your case based on the amount you plan to store. (Oh, also the SharePreferences handles concurrency issues for you.)
You could use Java's serialization to store Preference class(s) in binary files. These would be dramatically smaller then comparable PreferenceFile and can easily be passed through GZIPInputStream to make it smaller (or CipherInputStream) to encrypt it. I have found this alternate to be a powerful, simple, and cross-platform way to store app data where the power of SQLite is not needed.
(Sorry this isn't a direct answer.)
I've got an activity and I want to keep everything inside it (Bitmaps, texts, buttons..) so when the user restarts the phone and clicks on my app, everything is like the last time he used it.
Any idea?
I've been reading about the lifecycle of an application in Android, and i know the basics theoretically but I don't know how to implement it.
Thank you.
Actually, you don't need to do anything on objects such as Buttons and TextViews, since they do not change during your Activity's lifetime. When your application restarts, they just get recreated and they look the same anytime. Things that you want to save are possibly user inputs or downloaded files. If you have any of these, then I'd recommend learning this post, it describes different data storage mechanisms in Android. For different kinds of data you'll need different solutions, for example text inputs can be saved in SharedPreferences, but bitmaps should probably be saved in the file system. Hope this helps.
Maybe it is not the best solution, but you can try SharedPreferences and save different user data into different variables upon exiting.
When the app is restarted, read the values stored in the SharedPreferences and display these values in your respective views.
Other than SharedPreferences, you can also try out these various options according to the type of data you would want to persist!
My app needs to store data on the phone, but I'm not sure what's the more efficient method. I don't need to search through the data or anything like that. I just need to be able to save the app's current state when it closes and restore when it's back up. There is between 1mb and 10mb worth of data that will need saving.
There are basically a bunch of custom classes with data in them, and right now I have them as Serializable, and just save each class to a file. Is there any reason for me to change that to store it in SQLite?
If you where to use sqlite you could save as you go, and know that whats in the DB is pretty much uptodate if the app/activity holding the data is suddenly killed by the os. Other that that I cant see and obvious reason to use sqlite for your use-case.
Also for the sql approach you have a clear cut way to change the structure of your domain objects at a later time and to migrate the data from a old to a new version of your database. This can be done using serialized objects as-well, but then the objects needs to be duplicated, both new and old at the same time. And that to me sounds very very scary and messy, especially considering that you might need to go from version x to y, so you might end up with some pretty tricky problems if you ever need to update the domain objects.
And I can honestly not see any benefits of using the flat-file/serialized approach.
You mention in your question that the data is only meant to save the state of the app, therefore my initial response would be to keep it on the devices especially since you mention that the file size would not be much more than 10MB, which is quite reasonable.
So my answer to you would be to keep it as is on the device. If your usage of the information changes in the future, you should then reconsider this approach, but for now it's totally logical.
If you're only saving serialized classes, you could use an ORM mapper as discussed in this thread . This saves you the inconvenience of writing your own mapper and is easily extendable to new classes. Also, if your requirements change, you COULD lookup data.
The only reasons for changing your system to SQLite would be more comfort and maybe a more foolproof system. E.g. now you have to check if the file exists, parse the contents etc. and if you'd use SQLite, you don't have to verify the integrity of the data and Android also helps you a little. And you could use the data for other causes, like displaying them in a ListView.