Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharedpreference byte[] value cleared after app killed via 'Force Stop' or task manager

Problem

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.


Shared Preference Code

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;
    }

`byte[]` Code

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;
        }
    }

Any input would be greatly appreciated..

Sadly, I haven't been able to make any progress here. Any thoughts?


Update:

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.


Current Solution:

Removed the Base64 encoding of the SharedPreference Key for storage and retrieval and the value is now persisting in all cases.

like image 558
AnxGotta Avatar asked Aug 05 '16 15:08

AnxGotta


People also ask

What is SharedPreference?

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.

What do you call this method which deletes a single names preference?

Removing single preference: SharedPreferences settings = context.getSharedPreferences("PreferencesName", Context.MODE_PRIVATE); settings.edit().remove("KeyName").commit();

How do you clear preferences in flutter?

You can simply use clear() function with your variable it will clear all the shared preferences. SharedPreferences preferences = await SharedPreferences. getInstance(); await preferences. clear();


2 Answers

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 :)

like image 54
Elltz Avatar answered Sep 19 '22 15:09

Elltz


Try once with editor.commit() instead of apply(), see if that works

like image 33
Manjunath Hegde Avatar answered Sep 17 '22 15:09

Manjunath Hegde