Home » Android » Android: Copy/Duplicate SharedPreferences

Android: Copy/Duplicate SharedPreferences

Posted by: admin May 14, 2020 Leave a comment

Questions:

Is there a way to copy or duplicate a SharedPreference? Or will I need to get each variable from one and then put them in another?

How to&Answers:

Try Something Like this:

//sp1 is the shared pref to copy to
SharedPreferences.Editor ed = sp1.edit(); 
SharedPreferences sp = Sp2; //The shared preferences to copy from
ed.clear(); // This clears the one we are copying to, but you don't necessarily need to do that.
//Cycle through all the entries in the sp
for(Entry<String,?> entry : sp.getAll().entrySet()){ 
 Object v = entry.getValue(); 
 String key = entry.getKey();
 //Now we just figure out what type it is, so we can copy it.
 // Note that i am using Boolean and Integer instead of boolean and int.
 // That's because the Entry class can only hold objects and int and boolean are primatives.
 if(v instanceof Boolean) 
 // Also note that i have to cast the object to a Boolean 
 // and then use .booleanValue to get the boolean
    ed.putBoolean(key, ((Boolean)v).booleanValue());
 else if(v instanceof Float)
    ed.putFloat(key, ((Float)v).floatValue());
 else if(v instanceof Integer)
    ed.putInt(key, ((Integer)v).intValue());
 else if(v instanceof Long)
    ed.putLong(key, ((Long)v).longValue());
 else if(v instanceof String)
    ed.putString(key, ((String)v));         
}
ed.commit(); //save it.

Hope this helps.

Answer:

Here a version that also supports string sets.

public static void copySharedPreferences(SharedPreferences fromPreferences, SharedPreferences toPreferences) {
    copySharedPreferences(fromPreferences, toPreferences, true);
}

public static void copySharedPreferences(SharedPreferences fromPreferences, SharedPreferences toPreferences, boolean clear) {

    SharedPreferences.Editor editor = toPreferences.edit();
    if (clear) {
        editor.clear();
    }
    copySharedPreferences(fromPreferences, editor);
    editor.commit();
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressWarnings({"unchecked", "ConstantConditions"})
public static void copySharedPreferences(SharedPreferences fromPreferences, SharedPreferences.Editor toEditor) {

    for (Map.Entry<String, ?> entry : fromPreferences.getAll().entrySet()) {
        Object value = entry.getValue();
        String key = entry.getKey();
        if (value instanceof String) {
            toEditor.putString(key, ((String) value));
        } else if (value instanceof Set) {
            toEditor.putStringSet(key, (Set<String>) value); // EditorImpl.putStringSet already creates a copy of the set
        } else if (value instanceof Integer) {
            toEditor.putInt(key, (Integer) value);
        } else if (value instanceof Long) {
            toEditor.putLong(key, (Long) value);
        } else if (value instanceof Float) {
            toEditor.putFloat(key, (Float) value);
        } else if (value instanceof Boolean) {
            toEditor.putBoolean(key, (Boolean) value);
        }
    }
}

Answer:

The Kotlin version:

fun SharedPreferences.copyTo(dest: SharedPreferences) = with(dest.edit()) {
  for (entry in all.entries) {
    val value = entry.value ?: continue
    val key = entry.key
    when (value) {
      is String -> putString(key, value)
      is Set<*> -> putStringSet(key, value as Set<String>)
      is Int -> putInt(key, value)
      is Long -> putLong(key, value)
      is Float -> putFloat(key, value)
      is Boolean -> putBoolean(key, value)
      else -> error("Unknown value type: $value")
    }
  }
  apply()
}

Usage:

val prefs1 = getSharedPreferences("test1", MODE_PRIVATE)
val prefs2 = getSharedPreferences("test2", MODE_PRIVATE)

prefs1.copyTo(prefs2)

Answer:

I’m surprised that this answer has been considered useful.
By using with(dest.edit()) when using this.putString(key, value) is pointing to the preferences editor of dest not to the editor of extension. So it copy the values from to same destiny.
And I mean, prefs1.copyTo(prefs2) makes copy from prefs2 to prefs2.
You can test it by changing with(dest.edit()) to with(this.edit()).
It will work the other way around.

Consider this fix:

fun SharedPreferences.copyTo(dest: SharedPreferences) = with(this.edit()){
   dest.let { 
      for (entry in it.all.entries) {
         val value = entry.value ?: continue
         val key = entry.key
         when (value) {
            is String -> putString(key, value)
            is Set<*> -> putStringSet(key, value as Set<String>)
            is Int -> this.putInt(key, value)
            is Long -> this.putLong(key, value)
            is Float -> this.putFloat(key, value)
            is Boolean -> this.putBoolean(key, value)
            else -> error("Unknown value type: $value")
         }
      }
   }
   this.apply()
}