How can I save user-created objects to storage in android? - android

In my app, I have flashcard objects that the user creates themselves. Users can create as many flashcards as they want, but when they exit the app and return they need to be able to see the flashcards that they previously created and be able to delete them. I have it set up so that they can create/delete, but if they exit the app they will all delete automatically. What is the best way to save the information for a flashcard? It has at least 3 strings currently, the title, the front and the back.
I looked at a few, but am not sure how I would include all three strings in the saving options that are on the android developer site.
For example shared preferences, looks like you can only save certain settings, but it allows the user to change those settings.
The internal/external storage, although very different throw up the same problem, how to have unlimited number of objects and especially how to save all three strings separately.
This is the internal storage is shown below.
String FILENAME = "hello_file";
String string = "hello world!";
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
I don't see how you can save multiple number of objects or 3 different strings.
Does anyone see a solution to my problem?

SharedPreferences seem like the simplest way for you to achieve it, and I think you've misunderstood their usage, or confused the name with a 'Preferences' screen, as you can use the SharedPreferences methods to save anything (well, any basic datatype) persistently.
For example, I use it to save my app's JSON data (which might be a decent way for you to go in terms of saving you users' flashcards in a JSONArray).
/**
* Retrieves data from sharedpreferences
* #param c the application context
* #param pref the preference to be retrieved
* #return the stored JSON-formatted String containing the data
*/
public static String getStoredJSONData(Context c, String pref) {
if (c != null) {
SharedPreferences sPrefs = c.getSharedPreferences("AppPreferences", Context.MODE_PRIVATE);
return sPrefs.getString(pref, null);
}
return null;
}
/**
* Stores the most recent data into sharedpreferences
* #param c the application context
* #param pref the preference to be stored
* #param policyData the data to be stored
*/
public static void setStoredJSONData(Context c, String pref, String policyData) {
if (c != null) {
SharedPreferences sPrefs = c.getSharedPreferences("AppPreferences", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sPrefs.edit();
editor.putString(pref, policyData);
editor.commit();
}
}
Where the string 'pref' is a tag used to refer to that specific piece of data, so for example: "taylor.matt.data1" would refer to a piece of data and could be used to retrieve or store it from SharedPreferences

Related

How to use sharedPreference value in different classes in android

in main Activity i have following:
((TextView)findViewById(R.id.TextView02)).setText(getSharedPreferences("FearAlert", 1).getString("contactName", "Tap to select an Emergency Contact."));
((TextView)findViewById(R.id.TextView03)).setText(getSharedPreferences("FearAlert", 1).getString("contactNumber", ""));
now i want to use contactNumber value in ANOTHER Activty say activity2
in Activty2 is:
SmsManager.getDefault().sendTextMessage(??, null, "message",null, null, null);
return null;
what should i write in place of ?? above..help please..
In Java, there are... Never mind, In programming languages, there are variables where you can assign values to variables. like x=1; then use can use x+x=?; and will give you 2;
Here you can do
SharedPreferences sPrefs=getSharedPreferences("FearAlert", 1);
TextView tv=(TextView)findViewById(R.id.TextView02);
String YOUR_INTRESTING_STRING=sPrefs.getString("contactName", "Tap to select an Emergency Contact.");
And to pass it to the another Activity; You can put it in a Bundle
Intent i = new Intent(getApplicationContext(), YOUR_ANOTHER_ACTIVITY.class);
i.putExtra("name_of_value",YOUR_INTRESTING_STRING);
startActivity(i);
And retrive it in your AnotherActivity by
Bundle extras = getIntent().getExtras();
String value = extras.getString("name_of_value");
Preferences are typically name value pairs. They can be stored as “Shared Preferences” across various activities in an application (note currently it cannot be shared across processes). Or it can be something that needs to be stored specific to an activity (which is not discussed here).
The context object lets you retrieve SharedPreferences through the method
Context.getSharedPreferences().
getSharedPreferences("FearAlert", 1).getString("contactNumber", "");
OR
SharedPreferences myPrefs = this.getSharedPreferences("FearAlert", 1);
String contactNumber = myPrefs.getString(contactNumber, "nothing");
you can access you preferences everywhere in your app e.g. with following method:
/**
* Get a string preference by its key from the apps preferences file
*
* #param key of preference
* #return value of preference
*/
public String getStringPreference(String key) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
return pref.getString(key, "");
}
Just set your key, e.g. "contactName" as parameter. The preferences manager requires the application context via getApplicationContext().
Assuming you have created the SharedPreferences correctly:
SharedPreferences settings = getSharedPreferences("MY_APP", MODE_PRIVATE);
You can retrieve a preference in your method by:
SmsManager.getDefault().sendTextMessage(settings.getString("contactNumber"), null, "message", null, null, null);
Assuming you've set it with the "MY_APP" shared preference tag.
settings.edit().putString("contactNumber", "XXX-XXX-XXXX").commit();

Storing an arraylist for retrieval in Android

I'm currently working on an Android application that is going to be somewhat like a student planner. My backend is all java and I am currently stuck because i am storing the objects that i create from my backend to arraylist. Being java, these objects dissapear as soon as the programs terminate. Whats the easiest way that i can store my java objects for retrieval the next time i boot my application? Any help is much appreciated! Im developing on 2.3 and eclipse(juno).
One of the data storage options listed in the Android developer tutorial will be the easiest thing to do. Which is the best fit will depend on how much data you're storing and how you need to access it. As the page says, the SharedPreferences class is best for a handful of items; for larger data sets, you could use Java serialization or some other way to write them to a file on the phone's storage; and if your data are large and/or you need structured access to them, an SQLite database is your best bet.
You can use Shared Preferences to store your data. The SharedPreferences lets you persist key-value pairs of primitive data types in you application. You can't store an entire ArrayList with a single key, but you can iterate over the array and systematically generate a key for each value in the list. I usually do something like this:
public class SomeActivity extends Activity {
private ArrayList<Data> list; //We'll persist this array
/* snip */
//These strings can be anything - you just need something you can use to systematically generate distinct keys
public static final String LIST_KEY = "SomeActivity_List";
public static final String LIST_LENGTH_KEY = "SomeActivity_ListLength";
/**
* How this method works: It starts by getting a SharedPreferences object,
* which offers an API for persisting data. It then systematically generates
* Strings like "SomeActivity_List1", "SomeActivity_List2", "SomeActivity_List3",
* and so on to use as keys fot the 1st, 2nd, 3rd, etc. elements in the list. Then
* it Data.saveData(), a method defined below in the Data class, in order to give
* each Data object in the ArrayList an opportunity to persist its primitive
* members in the SharedPreferences.
*
* SomeActivity.restoreList() works similarly.
*/
public void saveList() {
SharedPreferences prefs = getPreferences(); //This method is part of the Activity class
SharedPreferences.Editor editor = prefs.getEditor();
//Save the length of the list so that when we restore it, we know how many
//Data objects to recreate.
editor.putInt(LIST_LENGTH_KEY, list.size());
editor.commit();
//This for loop is important - note how we concatenate i to each of the keys to give each element in list a distinct key
for(int i = 0; i < list.size(); i++)
{
String identifier = LIST_KEY + Integer.toString(i); //generate distinct keys
list.get(i).saveData(identifier, prefs);
}
}
public void restoreList() {
SharedPreferences prefs = getPreferences();
int length = prefs.getInt(LIST_LENGTH_KEY);
for(int i = 0; i < length; i++)
{
String identifier = LIST_KEY + Integer.toString(i); //re-generate distinct keys
Data data = new Data();
data.restoreData(identifier, prefs);
list.addLast(data);
}
}
public static class Data {
private int i;
private double j;
private String s;
public static final String I_KEY = "Data_I"
public static final String J_KEY = "Data_J" //strings can really be whatever, as long as they're distinct.
public static final String S_KEY = "Data_K"
/**
* How this method works: The SomeActivity.saveList() method generates a
* unique String ("identifier") for each of the Data objects it contains.
* This method uses that distinct string and makes some more distinct keys
* to store each of Data's primitive members.
*
* restoreData() works similarly when it rebuilds Data objects
*/
public saveData(String identifier, SharedPreferences prefs) {
SharedPreferences.Editor editor = prefs.getEditor();
editor.putInt(I_KEY + identifier, i);
editor.putDouble(J_KEY + identifier, j);
editor.putString(S_KEY + identifier, s);
editor.commit();
}
public restoreData(String identifier, SharedPreferences prefs) {
i = prefs.getInt(I_KEY + identifier);
j = prefs.getDouble(J_KEY + identifier);
s = prefs.getString(S_KEY + identifier);
}
}
}
This approach work recursively. If Data had an ArrayList as one of its fields, for example, it could systematically store all of the values in that list in SharedPreferences as well.
FYI: One of the implications of using SharedPreferences is that if the user uninstalls your app or clears the app data, the stored list will be deleted. Depending on the nature of your data, you may or may not want this behavior.

Constant Contact Id

Is there any kind of contact variable that is persistent between ROM flashes or factory resets ? I created an app that looks for the contacts id but apparently that changes when there is a sync from a factory reset or new ROM (and between devices). I need to store a unique identifier. Please help. Thank you.
If you are talking about sim data maybe you might figure out something. But if you are talking about an unique identifier the only efficient way i know is generating a UUID key and storing it locally and externally, as suggested by Reto Meier at Google I/O 2011. Here is my snippet (Don't mind my javadoc style ^^);
/**
* This is just a local solution. For world-wide usage,
* backup on a cloud is encouraged.
*
* #reference Reto Meier - Google I/O 2011
*
* #param context for accessing related shared preferences file
* #return unique id
*/
public synchronized static String getUniqueId(Context context)
{
String uniqueID;
//Open shared preferences file for PREF_UNIQUE_ID
SharedPreferences sharedPrefs = context.getSharedPreferences(PREF_UNIQUE_ID, Context.MODE_PRIVATE);
//Fetch id, if any.
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
//If no id saved into shared preferences before generate new one
if(uniqueID == null)
{
uniqueID = UUID.randomUUID().toString();
Editor editor = sharedPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
}
return uniqueID;
}

Appropriate storage and display of my bookmarks/history activity?

I want a simple bookmarks and/or history for my app, and I'm wondering what the most appropriate storage would be? A text in a text file or preference, or perhaps a database? Which would be most flexible across updates, and efficient for space and lookup time?
For the display, I'm thinking this would be a good starting point, but would it be easy to add an icon to some items?
Edit:
I finally set up a Bookmark activity that should connect to a database:
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bookmarkview);
Cursor cursor = managedQuery(getIntent().getData(), new String[] {Bookmark.TITLE, Bookmark.URL},
null, null, Bookmark.DEFAULT_SORT_ORDER);
setListAdapter(new SimpleCursorAdapter(this, R.layout.bookmarkitem, cursor,
new String[] { Bookmark.TITLE }, new int[] { android.R.id.text1 }));
findViewById(R.id.addBookmark).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
ContentValues values = new ContentValues();
values.put("url", _url);
values.put("title", _title);
// When the update completes,
// the content provider will notify the cursor of the change, which will
// cause the UI to be updated.
getContentResolver().update(_myuri, values, null, null);
}
});
}
Bookmark.java:
package com.tunes.viewer.Bookmarks;
import android.net.Uri;
import android.provider.BaseColumns;
/*
* Database will have:
* pk - primary key
* title - the name of the bookmark.
* url - the url.
*/
public class Bookmark implements BaseColumns{
public static final String AUTHORITY = "com.tunes.viewer";
/**
* The content:// style URL for this table
*/
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/Bookmarks");
/**
* The MIME type of {#link #CONTENT_URI} providing a directory of notes.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";
/**
* The MIME type of a {#link #CONTENT_URI} sub-directory of a single note.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";
/**
* The default sort order for this table
*/
public static final String DEFAULT_SORT_ORDER = "title";
/**
* The title of the note
* <P>Type: TEXT</P>
*/
public static final String TITLE = "title";
/**
* The url
* <P>Type: TEXT</P>
*/
public static final String URL = "url";
}
I seem to have fixed most of the problems I was having, but unfortunately it doesn't add to the database when I click the Add button (calling the onclick above). Furthermore, I added data to the database, but it doesn't show up in the view. What's wrong with the cursor/adapter here? Full source is here.
i would suggest, you go with database. It will be easy and efficient solution for your requirement.
A single table in sqlite will suffice to your requirements. as you will need to maintain a list of url you visited. this table will also serve your requirement of storing bookmark.
your table format could be something like this.
_____________________________________________________________________________________
Id(Auto-increment) | Title of page | Url of Page |name of icon(if needed) |isBookmark |
_____________________________________________________________________________________
This could be a good structure to achieve you requirement. set isBookmark to 0/1 to set specific link as bookmark or unbookmark it.
EDIT
I did not suggest you to use SharedPreferences and i wont (though it is straight forword and easy to implement) and reason lies in very definition of SharedPreferences which says:
"The SharedPreferences class provides a general framework that allows you to save and retrieve persistent key-value pairs of primitive data types. You can use SharedPreferences to save any primitive data: booleans, floats, ints, longs, and strings."
Now i can not imagine a single way to store ArrayList<String>(Urls) in one of these primitive datatypes.
There is one more work around.and it is Object Serialization. you can save your complete arraylist instance to a file and next time when you need this object, deseralize it similarly.. Here is the sample code for Serialization.
.
public void serializeMap(ArrayList<String> list) {
try {
FileOutputStream fStream = openFileOutput(namefile.bin, Context.MODE_PRIVATE) ;
ObjectOutputStream oStream = new ObjectOutputStream(fStream);
oStream.writeObject(list);
oStream.flush();
oStream.close();
Log.v("Serialization success", "Success");
} catch (Exception e) {
Log.v("IO Exception", e.getMessage());
}
}
But this approach is not much recommended though.
I agree with WareNinja- the SharedPreferences data areas would be sufficient for simple, non-relational data. This SO answer is very comprehensive in describing the nuances of implementing Activity and/or application-wide SharedPreferences.
The SharedPreferences framework will take care of all the data persistence minimising the amount of code you will need to write and your exposure to db-like 'update' transactions.
However be aware, in terms of expanding your application this medium is powerful but inflexible. The minute you feel the need to expand the type of data being stored move to SQLite or similar.
I suggest using SharedPreferences and/or memdiskcache, both works fast and seamlessly.
p.s. nothing against using sqlite, however i always try to avoid using db for client apps.
example lib to abstract local storage (no db!);
https://github.com/wareninja/generic-store-for-android
you can store and retrieve any type of data in key-value form,
sample code for loading java object from memdiskcache;
String keyPrefix = "blabla1";
if (GenericStore.isCustomKeyExist(GenericStore.TYPE_MEMDISKCACHE, keyPrefix, this)) {
mNewPoiDataList = (NewPoiDataList)GenericStore.getObject(GenericStore.TYPE_MEMDISKCACHE
, keyPrefix, this);
}

Using Shared Preferences with arrays

EDIT:
OK It turns out this code was working (more or less) I'd left in a line that reset the booleans I was trying to change. Thanks everyone for the help though.
Having trouble using SharedPreferences to read in saved array data when my app starts.
My _dPad Boolean and my _FreePlay Integer loads, saves and passes to and from my _renderer without any problems.
The trouble starts when I try and use some arrays
easteregg[] only has 2 entries right now so obviously I could just just turn them into separate variables but I wish to add more arras of longer length so this makes a convenient test example.
I've noted on the code what appears to happen (the easteregg[] settings just doesn't appear to have changed)
to read data:
// Read saved preferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
_renderer._dPad = prefs.getBoolean("_dPad", false); // * works ok *
_renderer._FreePlay = prefs.getInt("_FreePlay", 1); // * works ok *
_renderer.easteregg[0] = prefs.getBoolean("easteregg[0]", false ); // * not working
_renderer.easteregg[1] = true; // * even this is not working
setRenderer(_renderer);
to write data:
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
// As good a time as any to save current config
save = false ; // don't commit if nothing changed.
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = prefs.edit();
if (_renderer._dPad != prefs.getBoolean("_dPad",false)){ save = true ;
editor.putBoolean("_dPad", _renderer._dPad);}
if (_renderer._FreePlay != prefs.getInt("_FreePlay",1)){ save = true ;
editor.putInt("_FreePlay", _renderer._FreePlay);}
editor.putBoolean("easteregg[0]", _renderer.easteregg[0]);
editor.putBoolean("easteregg[1]", _renderer.easteregg[1]);
if (save == true){editor.commit();}
}
And in the .renderer class
// START SAVE DATA
public boolean _dPad ; // false no Virtual Pad *Works Fine*
public int _FreePlay ; // 1 = no free play *Works Fine*
public boolean[] easteregg = new boolean[2]; *Values don't load or save*
//public boolean easteregg[]; // tried this first *CAUSES CRASH*
// END SAVE DATA
Do I have to convert the arrays to strings? I don't get how to change them.
I put your code into a quick activity, creating just the shell of the renderer class as you have above and found that your save boolean is false, so it never commits the preferences.
I forced the save to true, and played around with it and everything worked fine from there.
I'd recommend adding checks to the easter eggs the same as you have for any other preference; test to see if the current value is the same as the saved value, and if not, set the save flag.
I would suggest saving the array as a string in a single variable. It appears you have an array of booleans. So loop through it to make it a series of either ints (0, 1) or the string "true" or "false" then save it to an int or string.
I suspect the probelm might be that your setting name contains square brackets. I think that in key value names, the key name must be a valid variable name. And square brackets are not allowed in variable names.
However i would also expect this to throw an error. Does the code work if you name you settings "easteregg_01" and "easteregg_02"?
The best solutions would be to convert your array into JSON string and store it as preference value. If you have small amount of data, you can as well stick with org.json classes provided by android. If you have more data, GSON pull parser would be better, as it utlizes pull parser. And if you are really lazy, you grab my small databinding library and do:
String jsonState = preferences.getString(GAME_STATE, null);
StateStorage storage = JSONUnmarshaller.unmarshall(new JsonReader(new
StringReader(jsonState)), StateStorage.class);
and it will instantiate java class for you and fill in the data. And to save:
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
StringWriter writer = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(writer);
JSONMarshaller.marshall(jsonWriter, ss);
editor.putString(GAME_STATE, writer.toString());
editor.commit();
Databinding library is available on github, or from maven central:
https://github.com/ko5tik/jsonserializer
PS: at the moment I work on injection of preference values ( at the moment primitives only):
https://github.com/ko5tik/andject

Categories

Resources