113

In Android can we store an object of a class in shared preference and retrieve the object later?

If it is possible how to do it? If it is not possible what are the other possibilities of doing it?

I know that serialization is one option, but I am looking for possibilities using shared preference.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
androidGuy
  • 5,553
  • 12
  • 39
  • 56
  • I add a helper library in case someone need it: https://github.com/ionull/objectify – Tsung Wu Aug 01 '14 at 07:20
  • Here is an example http://thegeekyland.blogspot.com/2015/11/serializing-and-deserializing-json-from.html – Arlind Hajredinaj Nov 30 '15 at 00:05
  • Here is an [answer](http://stackoverflow.com/a/39435730/6561141) to similar question. – mrtpk Sep 11 '16 at 11:53
  • Possible duplicate of [How Android SharedPreferences save/store object](http://stackoverflow.com/questions/7145606/how-android-sharedpreferences-save-store-object) – mrtpk Sep 11 '16 at 11:54
  • You can use this library which has lot of feautres inbuilt. https://github.com/moinkhan-in/PreferenceSpider/ – Moinkhan Jul 31 '18 at 03:42
  • Please have a look at this link https://stackoverflow.com/questions/7145606/how-android-sharedpreferences-save-store-object – VasanthRavichandran Nov 16 '18 at 09:18

12 Answers12

332

Yes we can do this using Gson

Download Working code from GitHub

SharedPreferences mPrefs = getPreferences(MODE_PRIVATE);

For save

Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(myObject); // myObject - instance of MyObject
prefsEditor.putString("MyObject", json);
prefsEditor.commit();

For get

Gson gson = new Gson();
String json = mPrefs.getString("MyObject", "");
MyObject obj = gson.fromJson(json, MyObject.class);

Update1

The latest version of GSON can be downloaded from github.com/google/gson.

Update2

If you are using Gradle/Android Studio just put following in build.gradle dependencies section -

implementation 'com.google.code.gson:gson:2.6.2'
Ben
  • 3,346
  • 6
  • 32
  • 51
Parag Chauhan
  • 35,760
  • 13
  • 86
  • 95
  • not working in my case. Even after putting jar in libs and setting in build path, Gson class not getting resolved. – Shirish Herwade May 28 '13 at 11:10
  • Clean project then try @ShirishHerwade – Parag Chauhan May 28 '13 at 12:01
  • @parag that also not working. Can you please tell me steps to use that jar to remove above error. Because I successfully added that jar in libs folder and then in "java build path" also tried to add externally storing json on my desktop – Shirish Herwade May 29 '13 at 04:38
  • @ShirishHerwade download working code http://www.mediafire.com/download/iued27pf025e1uw/GSonDemo.rar – Parag Chauhan May 29 '13 at 06:10
  • 9
    This answer would be even better if it also mentioned its limitations. What kind of object can and can't we store and retrieve in this manner? Obviously it will not work for all classes. – wvdz Jun 22 '14 at 11:07
  • 3
    `String json = gson.toJson("MyObject");` should be the object not a String. – Ahmed Hegazy Feb 18 '15 at 08:18
  • One important note should be taken when use this way: Date object won't be stored precisely ( millisecond will be ignored ) the reason is that Date object will be represented by toString() implicitly where no millisecond counted... so strongly I'd recommend to use long to represent time instead of Date object... – Maher Abuthraa Jul 01 '15 at 23:26
  • This has a problem with circular reference that leads to StackOverFlowException xD Read more here http://stackoverflow.com/questions/10209959/gson-tojson-throws-stackoverflowerror – phuwin Jul 29 '16 at 13:39
  • what to set when trying to save it as generic . Class obj = gson.fromJson(json, Class.class); . – Zar E Ahmer Aug 24 '16 at 07:17
  • It seems android Marshmallow throw Runtime Exception for this procedure. (Happen on release mode with debuggable false.) – Sarith Nob Mar 09 '20 at 09:53
  • @SarithNOB should work because not depend on any OS just we are storing string – Parag Chauhan Mar 15 '20 at 14:04
  • @ParagChauhan Oh yes, I see the problem is about converting empty string to object. Default value string getting from preference must "{}" when it is empty. Because "{}" is empty json object. – Sarith Nob Mar 19 '20 at 08:24
  • Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, *it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.* – Marcos Vasconcelos Apr 01 '20 at 18:02
  • @ParagChauhan Yes, that is it. After use default empty value as "{}", there is no more Runtime Exception anymore. Thank you! – Sarith Nob Feb 08 '21 at 01:38
44

we can use Outputstream to output our Object to internal memory. And convert to string then save in preference. For example:

    mPrefs = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor ed = mPrefs.edit();
    ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();

    ObjectOutputStream objectOutput;
    try {
        objectOutput = new ObjectOutputStream(arrayOutputStream);
        objectOutput.writeObject(object);
        byte[] data = arrayOutputStream.toByteArray();
        objectOutput.close();
        arrayOutputStream.close();

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Base64OutputStream b64 = new Base64OutputStream(out, Base64.DEFAULT);
        b64.write(data);
        b64.close();
        out.close();

        ed.putString(key, new String(out.toByteArray()));

        ed.commit();
    } catch (IOException e) {
        e.printStackTrace();
    }

when we need to extract Object from Preference. Use the code as below

    byte[] bytes = mPrefs.getString(indexName, "{}").getBytes();
    if (bytes.length == 0) {
        return null;
    }
    ByteArrayInputStream byteArray = new ByteArrayInputStream(bytes);
    Base64InputStream base64InputStream = new Base64InputStream(byteArray, Base64.DEFAULT);
    ObjectInputStream in;
    in = new ObjectInputStream(base64InputStream);
    MyObject myObject = (MyObject) in.readObject();
Kislingk
  • 1,427
  • 14
  • 23
  • Hi, I know this was posted a while ago, but are you sure the code you have for extracting the stored object is correct? I'm getting multiple errors on the last 2 lines whining about how explicit constructors need to be defined rather than simply having "new ObjectInputStream(byteArray)". Thanks for the help! – Wakka Wakka Wakka Mar 14 '13 at 01:47
  • Hi, I'm suddenly getting an EOFException on in = new ObjectInputStream(base64InputStream); I'm writing it to shared prefs in exactly the same way you are doing. What do you think could be wrong? – marienke Dec 09 '13 at 14:53
  • Do you have any exception when you write Object to pref? From SDK:Thrown EOFException when a program encounters the end of a file or stream during an input operation. – Kislingk Dec 09 '13 at 23:24
  • Kudos, this is the best solution I came across for this problem so far. No dependencies. However, it should be noted that in order to be able to use ObjectOutput/InputStream for an object, the said object and all custom objects within it must implement the Serializable interface. – user1112789 Apr 25 '15 at 19:06
16

Not possible.

You can only store, simple values in SharedPrefences SharePreferences.Editor

What particularly about the class do you need to save?

Blundell
  • 75,855
  • 30
  • 208
  • 233
  • 1
    Thanks.I want to store some data members of the class.And i don't want to store each values of data members using shared preference.I want to store it as an object.If not shared preference what are my other options? – androidGuy Mar 24 '11 at 11:25
  • 5
    Serialise it and store it, in a database (SQLite) / in a flat file. – Blundell Mar 24 '11 at 11:35
  • 5
    The answer is not complete. The possible solution is to transform the pojo into ByteArrayOutPutStream and save as String in the SharedPreferences – rallat Jun 06 '12 at 15:22
  • 28
    another option is saved it as json and then map it back. With GSON or jackSON is really easy – rallat Jun 07 '12 at 08:31
  • We can serialize the object and store to shared Preference. – mrtpk Sep 11 '16 at 11:40
  • 1
    Why is this marked as the correct answer? The other ones give an actual solution, this one just says "NO"... – Alejandro Bertinelli Dec 10 '17 at 14:41
  • 2
    let me get my time machine back to 2011 and figure that out – Blundell Dec 10 '17 at 21:51
  • You can use this library which has lot of feautres inbuilt. https://github.com/moinkhan-in/PreferenceSpider/ – Moinkhan Jul 31 '18 at 03:42
  • @AlejandroBertinelli Because this is the correct answer to the original question. Alexander said he already knew he can serialize an object and then store a string in the preferences. Well, if you first transform an object to a JSON, binary or other string format, probably using a 3rd party library, you can do it. But that's not the same as if the Android API would offer some possibility to store an object. – klenium Feb 26 '19 at 17:49
8

I had the same problem, here's my solution:

I have class MyClass and ArrayList<MyClass> that I want to save to Shared Preferences. At first I've added a method to MyClass that converts it to JSON object:

public JSONObject getJSONObject() {
    JSONObject obj = new JSONObject();
    try {
        obj.put("id", this.id);
        obj.put("name", this.name);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return obj;
}

Then here's the method for saving object ArrayList<MyClass> items:

SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);
SharedPreferences.Editor editor = mPrefs.edit();

Set<String> set= new HashSet<String>();
for (int i = 0; i < items.size(); i++) {
    set.add(items.get(i).getJSONObject().toString());
}

editor.putStringSet("some_name", set);
editor.commit();

And here's the method for retrieving the object:

public static ArrayList<MyClass> loadFromStorage() {
    SharedPreferences mPrefs = context.getSharedPreferences("some_name", 0);

    ArrayList<MyClass> items = new ArrayList<MyClass>();

    Set<String> set = mPrefs.getStringSet("some_name", null);
    if (set != null) {
        for (String s : set) {
            try {
                JSONObject jsonObject = new JSONObject(s);
                Long id = jsonObject.getLong("id"));
                String name = jsonObject.getString("name");
                MyClass myclass = new MyClass(id, name);

                items.add(myclass);

            } catch (JSONException e) {
                e.printStackTrace();
         }
    }
    return items;
}

Note that StringSet in Shared Preferences is available since API 11.

ricardopereira
  • 11,118
  • 5
  • 63
  • 81
Micer
  • 8,731
  • 3
  • 79
  • 73
  • Solved my problem. I want to add something. For first use we must check if the set is null. if (set != null){ for (String s : set) {..}} – xevser Jun 10 '16 at 08:07
  • @xevser I've added null check as suggested. Thanks. – Micer Oct 25 '16 at 08:34
6

Using Gson Library:

dependencies {
compile 'com.google.code.gson:gson:2.8.2'
}

Store:

Gson gson = new Gson();
//Your json response object value store in json object
JSONObject jsonObject = response.getJSONObject();
//Convert json object to string
String json = gson.toJson(jsonObject);
//Store in the sharedpreference
getPrefs().setUserJson(json);

Retrieve:

String json = getPrefs().getUserJson();
Ramesh sambu
  • 3,577
  • 2
  • 24
  • 39
  • Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable. – Marcos Vasconcelos Apr 01 '20 at 18:03
0

Using this object --> TinyDB--Android-Shared-Preferences-Turbo its very simple. you can save most of the commonly used objects with it like arrays, integer, strings lists etc

kc ochibili
  • 3,103
  • 2
  • 25
  • 25
0

You can use Complex Preferences Android - by Felipe Silvestre library to store your custom objects. Basically, it's using GSON mechanism to store objects.

To save object into prefs:

User user = new User();
user.setName("Felipe");
user.setAge(22); 
user.setActive(true); 

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(
     this, "mypref", MODE_PRIVATE);
complexPreferences.putObject("user", user);
complexPreferences.commit();

And to retrieve it back:

ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(this, "mypref", MODE_PRIVATE);
User user = complexPreferences.getObject("user", User.class);
Serhii Hrabas
  • 401
  • 1
  • 5
  • 12
  • Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable. – Marcos Vasconcelos Apr 01 '20 at 18:04
  • This is deprecated – IgorGanapolsky May 28 '20 at 17:31
0

You could use GSON, using Gradle Build.gradle :

implementation 'com.google.code.gson:gson:2.8.0'

Then in your code, for example pairs of string/boolean with Kotlin :

        val nestedData = HashMap<String,Boolean>()
        for (i in 0..29) {
            nestedData.put(i.toString(), true)
        }
        val gson = Gson()
        val jsonFromMap = gson.toJson(nestedData)

Adding to SharedPrefs :

        val sharedPrefEditor = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE).edit()
        sharedPrefEditor.putString("sig_types", jsonFromMap)
        sharedPrefEditor.apply()

Now to retrieve data :

val gson = Gson()
val sharedPref: SharedPreferences = context.getSharedPreferences(_prefName, Context.MODE_PRIVATE)
val json = sharedPref.getString("sig_types", "false")
val type = object : TypeToken<Map<String, Boolean>>() {}.type
val map = gson.fromJson(json, type) as LinkedTreeMap<String,Boolean>
for (key in map.keys) {
     Log.i("myvalues", key.toString() + map.get(key).toString())
}
CAZ
  • 119
  • 8
  • Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable. – Marcos Vasconcelos Apr 01 '20 at 18:04
0

Common shared preference (CURD) SharedPreference: to Store data in the form of value-key pairs with a simple Kotlin class.

var sp = SharedPreference(this);

Storing Data:

To store String, Int and Boolean data we have three methods with the same name and different parameters (Method overloading).

save("key-name1","string value")
save("key-name2",int value)
save("key-name3",boolean)

Retrieve Data: To Retrieve the data stored in SharedPreferences use the following methods.

sp.getValueString("user_name")
sp.getValueInt("user_id")
sp.getValueBoolean("user_session",true)

Clear All Data: To clear the entire SharedPreferences use the below code.

 sp.clearSharedPreference()

Remove Specific Data:

sp.removeValue("user_name")

Common Shared Preference Class

import android.content.Context
import android.content.SharedPreferences

class SharedPreference(private val context: Context) {
    private val PREFS_NAME = "coredata"
    private val sharedPref: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
    //********************************************************************************************** save all
    //To Store String data
    fun save(KEY_NAME: String, text: String) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putString(KEY_NAME, text)
        editor.apply()
    }
    //..............................................................................................
    //To Store Int data
    fun save(KEY_NAME: String, value: Int) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putInt(KEY_NAME, value)
        editor.apply()
    }
    //..............................................................................................
    //To Store Boolean data
    fun save(KEY_NAME: String, status: Boolean) {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.putBoolean(KEY_NAME, status)
        editor.apply()
    }
    //********************************************************************************************** retrieve selected
    //To Retrieve String
    fun getValueString(KEY_NAME: String): String? {

        return sharedPref.getString(KEY_NAME, "")
    }
    //..............................................................................................
    //To Retrieve Int
    fun getValueInt(KEY_NAME: String): Int {

        return sharedPref.getInt(KEY_NAME, 0)
    }
    //..............................................................................................
    // To Retrieve Boolean
    fun getValueBoolean(KEY_NAME: String, defaultValue: Boolean): Boolean {

        return sharedPref.getBoolean(KEY_NAME, defaultValue)
    }
    //********************************************************************************************** delete all
    // To clear all data
    fun clearSharedPreference() {

        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.clear()
        editor.apply()
    }
    //********************************************************************************************** delete selected
    // To remove a specific data
    fun removeValue(KEY_NAME: String) {
        val editor: SharedPreferences.Editor = sharedPref.edit()
        editor.remove(KEY_NAME)
        editor.apply()
    }
}

Blog: https://androidkeynotes.blogspot.com/2020/02/shared-preference.html

Bolt UIX
  • 5,988
  • 6
  • 31
  • 58
-2

There is no way to store objects in SharedPreferences, What i did is to create a public class, put all the parameters i need and create setters and getters, i was able to access my objects,

Ismael ozil
  • 573
  • 5
  • 6
-3

Do you need to retrieve the object even after the application shutting donw or just during it's running ?

You can store it into a database.
Or Simply create a custom Application class.

public class MyApplication extends Application {

    private static Object mMyObject;
    // static getter & setter
    ...
}

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ... android:name=".MyApplication">
        <activity ... />
        ...
    </application>
    ...
</manifest>

And then from every activities do :

((MyApplication) getApplication).getMyObject();

Not really the best way but it works.

luc.chante
  • 418
  • 7
  • 18
-7

Yes .You can store and retrive the object using Sharedpreference