I'm trying to create a system to save the list of levels that have already been played in my application.
I've been using Editor and SharedPreferences to store information on the phone.
But now I have a list of int to save
I've been trying to figure out something with
DataOutputStream out;
//Size
int resultSize = results.size();
out.writeInt(resultSize);
//All the levels ID
for (int idx = 0; idx < resultSize; idx++){
//l().debug("Lvl ID: "+results.get(idx));
out.writeInt(results.get(idx));
}
But then I don't know how to store this in the shared preferences.
I'm also concerned about size, this list of ID might get really big so I want to optimize the amount stored.(hence the DataStream)
any ideas
Jason
You could iterate through your list and construct a comma delimitted String from the ints. E.g. "1,2,15..etc", then just write this string to SharedPreferences. You would obviously have to tokenize it when you read it back.
How big is "really big" exactly? Considering it's a list of levels played by a human I am going to assert that it is "small" for what a smartphone can handle. Though, personally I would recommend this to go in a SQLite table of "completed" levels for ease of querying the information.
I don't think that you need the most efficient way. This data is small, go with what you know. Pick something simple and understandable, something easy to debug.
A flat file with every level int on a new line. You can't get much simpler than that. Sure, it's bigger than the most efficient way, but it's much easier to recover from corrupted files, much easier to debug.
Binary stream is the most efficient way how to save integers. If you have really a lot of numbers (megabytes), use DataOutputStream combined with ZipOutputStream.
Related
I'm making an Android application and want to create a "Favorites" list for some objects in the app. I wanna make the list accessible and editable in all my activities and I can't really figure out the best way to do this.
Shared preferences? Writing a small txt file to the device? What's the fastest way to do this?
Thanks in advance!
dependencies {
compile 'com.google.code.gson:gson:2.3.1'
}
Then when you want to save, convert your array into String:
ArrayList<Type> yourData = new ArrayList<Type>();
String dataStr = new Gson().toJson(yourData);
//put this dataStr in your shared preferences as String
To retrieve and convert back to an object is also simple:
String str = "";
//you need to retrieve this string from shared preferences.
Type type = new TypeToken<ArrayList<Type>>() { }.getType();
ArrayList<Type> restoreData = new Gson().fromJson(str, type);
If you want to create a Favorites list, use a SQLite Database.
There's really only four ways to store data.
Shared Preferences
Databases
Local files
Remote Server - Slowest since it depends on network connection, so let's skip this.
Between the remaining 3, SharedPreferences is a great option when used to store a single value. However, it's not a good option for storing a Favorites list, mainly because you can only store a single String.
You can still store it by combining all items in your list into one string, then splitting it each time. However, as your Favorites list gets larger, this single long String will too. Splitting and combining all the time isn't efficient.
SharedPreferences is still a decent option if you only have to store the Favorite's list, but since you want to edit it too, it becomes a less attractive solution.
Local Files and Databases are the better options, however local files require you to read in the file each time you want to use it. This process of reading and writing to a file isn't as efficient as using a Database, especially if you want to edit. For example, let's say you want to remove an item from the middle of your Favorite's list. This would require you to read in the file, edit it, then write the change into the file again. Not too pleasant when compared with the ease of the final solution.
Databases are the best option for this, mainly because it's designed to manage data. You can create a single Favorite's table and add each item as it's own individual row. Fetching the entire table becomes quick and easy. Fetching a single item becomes quick and easy. Adding a new item or removing a new item is also quick and easy.
I need to work with a persistent String Array (n Rows, 1 column).
* On first running the app, the String Array needs to be created empty.
* On subsequent app executions the Array will be populated from a File and the contents need to be available throughout the rest of the app.
* As the app is executed, the Array needs to be able to 'grow' in row count
* As the app is executed, the Array rows need to be able to grow in length
* The user will have the option to Clear the Array of previous entries.
* At the end, the String Array contents will be written back to a File.
I find a lot of references to Putting and Getting from an existing SharedPreferences String[] but, in the newness of my Android development, I am struggling with how to proceed.
EDIT Follows...
The data itself suggests using an Array
Example:
MAIN ST. F55 63 KY08:57 12142015--------KY11:24 12142015345TMH KY13:57 12142015
MAIN ST. F56 WYE123 IN08:57 12142015--------KY11:24 12142015--------KY13:57 12142015
1ST ST. F57 --------KY08:57 12142015--------KY11:24 12142015789FPF KY13:57 12142015
1ST ST. F58 456FPF KY08:57 12142015998FPF KY11:24 12142015--------KY13:57 12142015
1ST ST. F59 789TTM KY08:57 12142015--------KY11:24 121420151234DG KY13:57 12142015
I first need to have this data in a File
Then in one GUI I check for the existence of the file.
If one exists, fine
If none exists, I create one.
Then, in subsequent GUI's, I must check for the existence of parameters
If they do not already exist, add them to the existing data lines.
If they already exist, notify the user
And so on and on.
Then when all of the current 'pass' data has been collected via multiple, separate GUI's, I have to write out the whole data-set into the file.
My reason for thinking that I need a SharedPreference approach is the need to find and check data from GUI to GUI as the user progresses through the app.
If that 'belief' is wrong, I am open to better approach suggestions.
EDIT 2 follows....
On further study of web references, I am beginning to think that perhaps the best approach for this data and how the data needs to change might be to use a SQLite approach. Any ideas about this?
Any assistance/suggestions you might have would be greatly appreciated.
i would discourage you from using sharedpreferences for anything else than preferences. means things that change rarely - really rarely and are really lightweight. do not put much data in there. less is better. the data structures underlying sharedpreferences are not a database.
another note. it is not a string list, but it would be a string set. sets are not necessarily ordered, nor do they necessarily keep their order. means - it is not rows. its a collection of strings that can come back in any fun order (usually there is some, but that depends on the implementation which i do not know)
now you could go and make your own list, your own data structure, save it into a string and read it out, use json to do exactly that or something similar, or better - use a database, which would exactly do that.
http://developer.android.com/training/basics/data-storage/databases.html
explains it, but as you'll see its something that might take some time.
now dont get me wrong, but i have to warn you about the following approach. it is valid, but has many problems and is far from thread safe. it will not be a problem as long as you only open it from the ui thread and do not keep anything in memory to cache - if you do it will create lots of problems.
your problem of adding a line and clearing can be solved by using a file. just a simple file
look here
http://developer.android.com/training/basics/data-storage/files.html#WriteInternalStorage
the change is to append when writing:
openFileOutput("filename", Context.MODE_APPEND);
see the context mode? now you can basically just write one line and append every time.
if you wanna clear the file, just deleteFile("filename")
this is as said not threadsafe, but can be a viable option if used carefully.
Please follow this step to achieve what you want with sharedPreference
create the class Parent for SharePreference
Create your empty Array
Convert Your empty array to String and put it on SharedPreference
to call your empty array from sharedPreference
Call your sharedPreference using your key
Convert the String to array
You get your array from the sharePreference
Hope it helps, and maybe this link will help you :
http://www.androidhive.info/2012/08/android-session-management-using-shared-preferences/
You can use my open-source library called prefser, which solves this problem and uses SharedPreferences and Gson under the hood. It's basically wrapper for default Android mechanism.
You can use it in the following way:
Prefser prefser = new Prefser(context); // create Prefser object
prefser.put("key", Arrays.asList("one", "two", "three")); // save array of Strings
String[] value = prefser.get("key", String[].class, new String[]{}); // read array of Strings
For more information check repository of the project, tests and README.md file.
Link: https://github.com/pwittchen/prefser
Please note, SharedPreferences have some limitations and shouldn't be used for storing large amount of data. If you expect a lot of data, consider using SQLite database or another type of database (e.g. with NoSQL or similar approach if you strive for simplicity).
OK, based on the data, how it needs to be manipulated and the pros and cons of using a SharedPreferences approach, I have decided to go with a SQLite approach.
With that approach I should be able to readily check:
* if the necessary table exists (if not create it)
* if the necessary Field1 + Field2 exists (if not create a new record)
* and I will be able to modify the record's Field3 contents as needed
Then when the user's actions are complete I can convert the SQLite table 'records' into strings and write them out as a File and then either DROP or PURGE the associated SQLite table (until needed next time).
I sincerely appreciate all of your suggestions.
Thank you.
I want to save a lot of strings with SharedPreferences class .
These strings are quit long.
I really want to know the maximum length of a string that can be save in shared preferences in android.And Also How much size of data i can store in This SharedPrefernces class.
As per android architecture there is no such limit to store data in SharedPreference. Better way is to database (SQLite) when you have to deal with huge amount of data
I read somewhere that there is no hard limit other than Integer.MAX_VALUE ( maximal string length). But it is not advisable to store that much on shared preferences, as this is XML file which must be parsed and you will have a problems while parsing it.
I used to store about 50-100KBytes there. It worked.
The exact answer obtained manually is: maximum Unicode symbol's size is 5657632 symbols (or from [0 to 5657631]) in my case. It's some about 2.7MB for SharedPReference.Editor .
Rather large storage.
You ca use this size twice:
PreferenceManager.getDefaultSharedPreferences(c)
context.getSharedPreferences("<key>", <Mode>);
Of course is't limit for SharedPreferences but if system won't have enough memory it is one first stuff what DELETE it, you remember it.
The thing is I need to store something like:
100 strings
20-30 ints
As you can see, it's a pretty large number, and you might say "Use sql"! I would use sql but for me it looks kinda alien. It's a lot of code, and after that I can't find a tutorial that shows you: look, you make a database with tables like this, and then you read it like this, you can also search in it like this...
Can you please give me the best method to save that data? And if you say sql, please give me a tutorial or something that shows me how to do what I said above.
I would say you should look into SQLite and try to learn that. But if you really want to stay away from SQL you could use putStringSet to store your strings in SharedPreferences. Now there isn't a thing for putIntSet but you could convert your ints to strings using String.valueOf(myInt) and save it using the same putStringSet. I would like to be clear though, I think that a database is the way to go on this but this method should work for you.
If you use SQl, look at ORMLite, which will let you store objects in the db (http://ormlite.com/). For 100 strings, if they're basically name/value pairs, just use SharedPreferences http://developer.android.com/reference/android/content/SharedPreferences.html. Could also use static string resources, as mentioned.
I have a few questions concerning the application I'm designing. I have many different routes I could try in order to get what I wanted, but I thought I would get suggestions instead of doing trial and error.
I'm developing a simple app that has one Game screen (activity) and a main menu to start the game. The game screen will have two buttons, "Next" and "Repeat". Every time "Next" is hit, a new sentence in a different language (with the english translation below it) will appear, audio will pronounce the sentence, and hopefully I can get a highlighter to highlight the part of the sentence being spoken. You can guess what the Repeat button does.
My question is, what do you guys think would be the best way to store these sentences so they can be randomly picked out? I thought about making an array of structures or classes with the English definition, audio, and sentence in each structure. Then using a random iterator to pick one out. However, it would take a long time to do this approach and I wanted to get some ideas before I tried it.
Also, I'm not sure how I would print the sentence and definition on the screen.
Thanks!
Using an array of structs/classes seems like that would be the normal way to go.
Not really sure what you mean by a random iterator, but when picking out random sentences from the array of sentences, you might want to avoid repeats until you've gone through all the elements. To do that, you can make a second array of indices, select one at random from those, use the element that corresponds to that index, and remove that number from the array of indices.
In Java, that would look something like
ArrayList<Sentence> sentences;
ArrayList<Integer> indices;
Random rand;
private void populateIndices() {
for(int i = 0; i < sentences.size(); i++)
indices.add(i);
}
public Sentence getNextSentence() {
if(indices.isEmpty())
populateIndices();
int idx = rand.nextInt(indices.size());
int val = indices.get(idx);
indices.remove(idx);
return sentences.get(val);
}
Quite frankly I would load out of copyright books from Project Gutenberg and randomly pull sentences from them. I would then pass the sentences into Google APIs to translate and pronounce the sentences. Relying on external services is at the very heart of what a connected OS like Android is made for. It would be a much more compelling use of the platform than a canned Rosetta Stone like CD solution and your ability to tap into a broader amount of content would be increased exponentially.