I'm saving a byte[]
in my shared preferences. I am able to close the app and reopen it with the value persisting in the Shared Preferences. When running the app and closing it via the 'Task Manager' or 'Force Close', the Shared Preference value for the byte[]
is cleared. I don't understand this because other values persist fine.
This lead me to believe that this was due to some gson or Shared Preference issue with the byte[]
so I converted it to a String and I still have the issue.
Edit:
I save the data during normal activity usage... after onCreate()
, for example. It's not during onPuse()
or onDestroy()
I forgot to mention this. It would make sense if I did call it here and one or both of those weren't being called on the 'Force Close' scenario.
Slightly modified to remove app specific implementation and data
private static final String SHARED_PREFERENCES_FILE_NAME = "SharedPreferenceName";
public static void setSharedPreferenceObjectBase64Encoded(Context context, String key, Object object) throws Exception {
// Need an editor to update shared preference values
SharedPreferences.Editor editor = context.getSharedPreferences(SHARED_PREFERENCES_FILE_NAME, Context.MODE_PRIVATE).edit();
Gson gson = new GsonBuilder().serializeNulls().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create();
String encodedKey = Base64.encodeToString(key.getBytes(), 0, key.getBytes().length, Base64.DEFAULT);
String stringObject = gson.toJson(object);
String encodedObject = Base64.encodeToString(stringObject.getBytes(), 0, stringObject.getBytes().length, Base64.DEFAULT);
editor.putString(encodedKey, encodedObject);
editor.apply();
}
public static Object getSharedPreferenceObjectBase64Encoded(Context context, String key, Class<? extends Serializable> objectClass) throws Exception {
// Need an editor to update shared preference values
SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_FILE_NAME, Context.MODE_PRIVATE);
Gson gson = new GsonBuilder().serializeNulls().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create();
String encodedKey = Base64.encodeToString(key.getBytes(), 0, key.getBytes().length, Base64.DEFAULT);
String encodedObject = prefs.getString(encodedKey, null);
if (encodedObject == null) {
throw new NullPointerException("encodedObject is null : No shared preference exists for key.");
}
String decodedObject = new String(Base64.decode(encodedObject, Base64.DEFAULT));
if(decodedObject == null){
throw new NullPointerException("decodedObject is null : Json decoding error.");
}
Object resultObject = gson.fromJson(decodedObject, objectClass);
if (resultObject == null) {
throw new NullPointerException("resultObject is null : Json decoding error.");
}
return resultObject;
}
public static final String VALUE_KEY= "value.key";
public static void saveTheValue(Context context, byte[] encryptedPin) {
try {
USharedPreferenceManager.setSharedPreferenceObjectBase64Encoded(context, VALUE_KEY, encryptedPin);
} catch (Exception e) {
}
}
public static byte[] getTheValue(Context context) {
try {
return (byte[]) USharedPreferenceManager.getSharedPreferenceObjectBase64Encoded(context, VALUE_KEY, byte[].class);
} catch (Exception e) {
return null;
}
}
Sadly, I haven't been able to make any progress here. Any thoughts?
As per Super-califragilistic recommendation, I iterated through the key/value pairs in the SharedPreferences immediately before retrieving the value. I was Base64 encoding my key and value values; in order to read the key to ensure the value was in the SharedPreferences I had to use the keys in plain text. This solved the issue for me as the byte[]
value was now being retrieved properly.
This seems strange to me but I can use it as a solution. I would still like to Base64 encode the keys, but it's not incredibly important.
Removed the Base64 encoding of the SharedPreference Key for storage and retrieval and the value is now persisting in all cases.
A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. Each SharedPreferences file is managed by the framework and can be private or shared. This page shows you how to use the SharedPreferences APIs to store and retrieve simple values.
Removing single preference: SharedPreferences settings = context.getSharedPreferences("PreferencesName", Context.MODE_PRIVATE); settings.edit().remove("KeyName").commit();
You can simply use clear() function with your variable it will clear all the shared preferences. SharedPreferences preferences = await SharedPreferences. getInstance(); await preferences. clear();
This line of code String encodedObject = prefs.getString(encodedKey, null);
means if the key does not exist it should return null, hence your key that you are checking does not exist.
To validate if your key/value exist use this code
for(Entry<String, ?> en : sharedPref.getAll().entrySet()){
en.getKey();//key
en.getValue();//value
}
you could stop that from happening override
onPause()
in the Activity
or Fragment
and call saveTheValue(Context context, byte[] encryptedPin)
if you detect you need to save data or have already tried saving data eg.
private boolean forceSaveInOnPause= false;//global variable
//in your saving method
....//after you save
forceSaveInOnPause = true;
//in your onPause of Activity
if(forceSaveInOnPause){
//re-save
forceSaveInOnPause = false;
but since you already have a solution scratch all that :)
Try once with editor.commit(
) instead of apply()
, see if that works
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With