【问题标题】:SharedPreferences will not save/load in PreferenceActivitySharedPreferences 不会在 PreferenceActivity 中保存/加载
【发布时间】:2011-09-23 22:06:51
【问题描述】:

编辑: 下面描述的问题是由于一个非常特殊的设备问题而不是由任何与编码相关的问题引起的。

我有一个preferenceActivity,其中有许多checkBoxPreferences。 checkBoxPreference 假设保存默认的共享首选项文件,然后在我打开应用程序时再次调用以更新 UI。

这并没有像想象的那样发生。 如果我关闭应用程序并重新打开它,我的值将保持原样,但如果我使用任务管理器结束应用程序或者如果我重启手机(当应用程序未运行时),则调用 defaultValues再次。

所以,我在 onResume() 中创建了一个 SharedPreference 来测试它。

SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

然后我检查该共享首选项中是否有键。

pref.contains("myCheckBoxPreference");

当我关闭并重新打开它时,它返回 true。如果我用任务管理器关闭或关闭并重新打开手机,则返回 false。

所以,我尝试手动设置 SharedPreference

SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("myCheckBoxPreference", myCheckBoxPreference.isChecked());
editor.commit();

然后当 checkboxpreference 值改变时我调用了它。我还尝试在 onStop 和 onPause 中调用它。不过,如果我关闭应用程序并重新打开它,pref.contains 会返回 true,但如果我关闭并重新打开手机电源,它会返回 false。

然后我尝试使用 SharedPreferences 文件。

在类声明中:

public static final String PREFS = "prefs";

在 onResume() 中:

SharedPreferences pref = this.getSharedPreferences(PREFS, 0);

同样的行为,如果我只是关闭应用程序并重新打开它,pref.contains 仍然返回 true,但如果我关闭并重新打开手机,它会返回 false。

然后我尝试将 myCheckBoxPreference 的键值更改为与 CheckBoxPreference 的 xml 键不匹配的值,它仍然具有相同的效果。

我把手机里的应用卸载了,然后关机再开机,再重新安装,还是一样的效果。

【问题讨论】:

  • 我很想在你测试这个时看到 logcat 的输出,一个完全用 onCreate 编写的精确测试用例,它只是打开首选项并保存一个值,然后在下次你读回来启动程序,你的 MYPREFS 常量的内容是什么。您真的无法读回首选项,还是在您启动 PreferenceActivity 子类时它们根本没有出现在 DialogPreference GUI 中?
  • 好吧,我会发布,但我真的是 android 新手,老实说不知道如何使用 logcat,我只是发出 Toast 通知来告诉我事情是否正确。 (无论如何我觉得这更有用,因为我可以在应用程序运行时轻松查看 toast。但是,在 toast 通知中,当我之前将布尔值保存为 true 时,它​​表示布尔值为 false。当从主要活动和调用 sharedpreference 的另一个活动。而且 GUI 更新似乎不是问题,因为它在重启手机之前工作。
  • 在 Android 2.3.7 上观察到相同的行为。虽然我注意到旋转设备就足够了,这样活动就被破坏了,onCreate 再次使用新的首选项触发。
  • @jakar 在加载设置后添加Log.d("prefstest", "Pref == " + pref); 之类的行,它会将数据放到 Eclipse 中的 logcat 输出中。它也可以通过在终端窗口上键入adb logcat 来阅读。非常方便。

标签: android sharedpreferences preferenceactivity preference taskmanager


【解决方案1】:

我刚刚解决了,我很确定。我没有代码错误,我的应用程序也没有任何问题(无论如何我不相信。)

我创建了一个名为“testproj”的新项目,然后我从我的设置 PreferenceActivity 中复制了所有代码,将其粘贴到 TestprojActivity 中,然后我从它所依赖的 xml 中复制了代码,然后将其粘贴到 main.xml测试项目。

然后我在 Samsung Captivate 上安装了 TestProj,更改了设置,通过 RAM 管理(我拥有的自定义 ROM 的功能)清除了 ram,然后设置卡住了。然后我重启手机,设置仍然存在,就像我配置它们一样。

当我手动设置它们时,它们都保持不变:

PreferenceManager.getDefaultSharedPreferences();

并且无需手动将它们保存到 SharedPreferences。

由于它不是我的手机,我还没有尝试过,但我认为恢复出厂设置可以完全修复它 编辑:我能够在新的 Samsung Captivate 和 Samsung infuse 上进行测试,并且效果很好。

我浪费了很多时间试图弄清楚这一点,我希望它对其他人有所帮助。 :)

【讨论】:

  • 听起来像下面 Paul 的 answer 是相关的。
  • 我不知道三星 Captivate 是三星 Galaxy S 的变体。似乎 David Caunt 认为这是该模型的一个问题是正确的。
  • 8 年后,我浪费了好几个小时想知道我的代码出了什么问题......原来这只是设备的问题
【解决方案2】:

我在三星 Galaxy S 上遇到了可能类似的问题,其中偏好 XML 文件的权限以某种方式更改/损坏。

日志显示某些主机进程未能读取文件,导致所有设置重置为默认值。我不记得确切的错误消息,但它与“/path/to/preferences/file.xml 的权限被拒绝”类似。

我的解决方案是通过设置、应用程序、管理应用程序、MyApp、删除数据来删除应用程序数据。这会删除与应用关联的首选项文件,问题立即消失。

我认为这是一个孤立的事件,因为我没有在各种 Android 设备(包括 Galaxy S II)上再次遇到它。

【讨论】:

  • 奇怪的是,当我去管理应用程序时,“删除数据”是灰色的并且“数据.......0.00B”。 TestProj 也发生了同样的事情,但手机将在下周内更换,因此我很快就能对其进行真正的测试。
  • 我相信 Galaxy S 上的一个常见问题 - 首选项权限已损坏的错误。我有一些用户报告了它。
  • @David-Caunt 很高兴知道这一点;我担心我在做一些愚蠢的事情。
  • 我在几个论坛上看到过它的报道,并且重新安装通常会修复它。三星没有消息,但他们的代码已被许多开发人员预定。
  • 我有一个用户在三星 Infuse 上遇到类似问题,收到此错误:尝试在未经许可的情况下读取首选项文件 /dbdata/databases/com.munzee.android.client/shared_prefs/MunzeePrefs.xml .我试图将 MunzeePrefs.xml 文件名更改为 UID,但看起来权限是在路径中的 FQN 上设置的。有关如何解决此问题的任何建议?卸载/重新安装应用程序不起作用。建议用户的唯一解决方案可能是恢复出厂设置。知道在哪里向三星报告错误吗?
【解决方案3】:

在客户端的主要测试设备上,我遇到了同样的问题。使用的设备是具有 SDK 级别 8 (2.2.1) 的三星 Galaxy S。

奇怪的行为是SharedPreferences要么没有保存,要么在恢复出厂设置后过于持久,也就是说重新安装应用程序后它们没有被删除。

由于当前的 distribution 为 2.2.x,而且售出的三星 Galaxy S 设备数量为数百万,发生此问题的可能性很大

因此,实施用于保存首选项的解决方法被认为是至关重要的。

为了收集详细的特征以尖锐地隔离此解决方法,是否也遇到该问题的每个人请在此处提供相应的内核版本System.getProperty("os.version")?

我在想这样的事情:

// !! I know that 2.6.32.9 is not yet correct. This would be a false positive !!
if ((System.getProperty("os.version").startsWith("2.6.32.9"))
    && (android.os.Build.DEVICE.contains("GT-I9000")))
    useInternalStorage();
else
    useSharedPreferences();

一旦准备好并且有人感兴趣,我也可以在这里发布真实代码。


编辑:一些附加信息:

面临该问题的设备:

物业 |价值观 ---------------------------------+---------------- -------------------- 构建.设备 | “GT-I9000T” Build.VERSION.INCREMENTAL | “UBJP9” Build.VERSION.RELEASE | “2.2.1” Build.VERSION.SDK | 8 System.getProperty("os.version") | “2.6.32.9”

类似设备未遇到该问题:

物业 |价值观 ---------------------------------+---------------- -------------------- 构建.设备 | “GT-I9000” Build.VERSION.INCREMENTAL | “AOJP4” Build.VERSION.RELEASE | “2.2” Build.VERSION.SDK | 8 System.getProperty("os.version") | “2.6.32.9”

【讨论】:

  • 我现在使用的设备可以工作,但是在您的测试设备上,如果您调用editor.clear().commit() 清除该首选项文件的所有值,那么值是否保存成功?另外,如果您更改它以使 prefs 文件具有不同的名称,会发生什么情况?以前我没想过要尝试这些步骤,我不再有故障的星系。
【解决方案4】:

在设置值之前尝试清除编辑器。我有同样的问题,它对我有用。 示例:

Editor e = PreferenceManager.getDefaultSharedPreferences(getParent()).edit();
e.clear();
e.putStringSet(key, value);

【讨论】:

  • 感谢您的意见,但我遇到的问题实际上是设备问题。我描述的问题没有理由存在于设备或操作系统错误之外。此外,您不必clear() 来写入新值,除非您只是想将您的应用设置回其默认状态。
【解决方案5】:

可以通过使用 sharedUserId 来解决权限问题,对于任何已签名的应用程序都应该相同。

http://developer.android.com/reference/android/R.attr.html#sharedUserId

【讨论】:

    【解决方案6】:

    我也遇到了保存然后检索数据的问题。我将保存和加载代码放在一个扩展应用程序的类中,因为我想要一个数据实例。我可以看到字符串被保存,LogCat 中没有错误,但是当我尝试加载它时,再次没有错误,我的字符串为空。我从来没有检查过数据是否真的进入了文件,所以我不知道保存或加载是否失败或两者兼而有之。

    我的代码大致如下:(comboToSave 只是 Gson 从一个简单的数据类生成的字符串)

    一种保存方法:

      SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE); 
      SharedPreferences.Editor editor = sharedPref.edit();
      editor.putString(getString(R.string.prefCombos), comboToSave); 
      editor.commit();
    

    以另一种方式加载:

      SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
      String loadedComboText = sharedPref.getString(getString(R.string.prefCombos), "");
    

    在头疼不已并且不知道该怎么做之后,我更改了从

    检索 sharedPref 值的代码

    SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);

    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

    关于两者之间的区别还有更多here(尽管在我的情况下看起来完全一样)

    我的 Galaxy S3 上的结果仍然相同。但是,在包括 VD(虚拟设备)在内的其他设备上测试这两个版本都有效。

    在代码的第一个版本中,我从调用活动中传递了活动;从从用户那里收集最后一点数据的活动中保存,并从我的主要活动中加载,以便在应用启动时准备好它。

    我昨晚玩了卸载应用程序并重新安装,关闭设备然后再次打开无济于事。

    我现在已将保存和加载方法从应用程序类移动到我完成输入的活动,即加载和保存代码现在都在同一个活动中。我已经用两种代码变体对此进行了测试,它们都可以工作。我拿回我保存的东西。然后我将所有代码移回 Application 类并且它可以工作;这让我相信,通过所有的安装/卸载,我以某种方式设法让它工作。 要点是:代码是正确的 - 如果它不起作用,则可能是设备和/或设置的原因

    【讨论】:

      【解决方案7】:

      我也遇到了同样的问题,苦恼了一阵子,终于找到了解决办法, 而且很简单,直接传递activity的引用,不使用任何通用上下文

      public SessionManagment(Activity mContextActivity){
      //  this.contextActivity = mContext;
          sharedPrefSession =  mContextActivity.getSharedPreferences(
                  Constants.SHARED_PREFERANCES_LIGHT_TIGER_SESSION_FILE_NAME, 
                  Context.MODE_PRIVATE);
      
      }//enden constructor 
      

      上面的代码是我为会话管理编写的类的构造函数,并且 当我在 AsyncTask 的主 ActivityFramgment 的代码中调用它时,我这样称呼它

      SessionManagment sessionManagment = new SessionManagment(referanct2thisActivity);
      

      其中referanct2thisActivity是在像这样的片段活动的“onCreate”函数中定义的

      referanct2thisActivity = this;
      

      希望以后能帮助到其他人

      【讨论】:

      • 感谢您的帮助,但我的实际问题是由于设备故障。
      猜你喜欢
      • 2013-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多