【问题标题】:Sharedpreference byte[] value cleared after app killed via 'Force Stop' or task manager通过“强制停止”或任务管理器杀死应用程序后,Sharedpreference byte[] 值被清除
【发布时间】:2016-12-12 02:43:35
【问题描述】:

问题

我正在共享偏好设置中保存byte[]。我可以关闭应用程序并使用共享首选项中保留的值重新打开它。当运行应用程序并通过“任务管理器”或“强制关闭”将其关闭时,byte[] 的共享首选项值将被清除。我不明白这一点,因为其他值仍然很好。

这让我相信这是由于 byte[] 的一些 gson 或 Shared Preference 问题,所以我将它转换为字符串,但我仍然遇到问题。

编辑:
例如,我在正常活动使用期间保存数据......在onCreate() 之后。不是在onPuse()onDestroy() 期间我忘了提这个。如果我确实在这里调用它并且在“强制关闭”场景中没有调用其中一个或两个,那将是有意义的。


共享偏好代码

稍作修改以删除应用特定的实现和数据

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[]` 代码

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

任何意见将不胜感激..

很遗憾,我在这里没有取得任何进展。有什么想法吗?


更新:

根据 Super-califragilistic 建议,我在检索值之前立即遍历 SharedPreferences 中的键/值对。我是 Base64 编码我的键值和值;为了读取密钥以确保值在 SharedPreferences 中,我必须以纯文本形式使用密钥。这解决了我的问题,因为现在可以正确检索 byte[] 值。

这对我来说似乎很奇怪,但我可以将其用作解决方案。我仍然想对密钥进行 Base64 编码,但这并不是非常重要。


当前解决方案:

删除了用于存储和检索的 SharedPreference Key 的 Base64 编码,该值现在在所有情况下都保持不变。

【问题讨论】:

  • 为什么需要用 GSON 序列化一个字节数组?
  • 你如何验证它是否被清除?因为它是空的?
  • 我确认它已被清除,因为它为空,是的。 @Super-califragilistic
  • @MarcinKoziński 我使用这个通用函数对我的共享偏好条目进行 Base64 编码。您对使用字节数组条目有什么想法?
  • 您的数据未清除,您的密钥不存在,要真正验证您的数据是否已清除,请使用此代码for(Entry&lt;String, ?&gt; en : sharedPref.getAll().entrySet()){ en.getKey(); en.getValue(); } 然后如果您没有找到密钥/值对,那么您可以说是的,我现在只能说强制关闭正在调整您的密钥形成,因此您检索它的密钥是不同的,prefs.getString(encodedKey, null); 第二个参数是如果密钥不存在返回 null,请验证并返回或发布您在活动中调用保存函数的位置或任何地方

标签: android gson sharedpreferences


【解决方案1】:

editor.commit(尝试一次)而不是apply(),看看是否有效

【讨论】:

  • 它不会改变结果。感谢您的建议。
【解决方案2】:

这行代码String encodedObject = prefs.getString(encodedKey, null); 表示如果 key 不存在它应该返回 null,因此您正在检查的密钥不存在。

要验证您的键/值是否存在,请使用此代码

for(Entry<String, ?> en : sharedPref.getAll().entrySet()){
      en.getKey();//key
      en.getValue();//value
}

您可以在ActivityFragment 中阻止这种情况发生overrideonPause(),如果您检测到需要保存数据或已经尝试保存数据,请致电saveTheValue(Context context, byte[] encryptedPin)

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;

但是既然你已经有了解决方案,那就从头开始吧:)

【讨论】:

    【解决方案3】:

    我认为在读写时使用 Base64.NO_PADDING 而不是 Base64.DEFAULT 可能会解决问题。

    【讨论】:

    • 我试了一下,结果相同,但值没有持续存在。感谢您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多