"Starting over" with shared prefs content when something goes wrong -- looks to me like a feature, and a useful one: sometimes storage goes bad, files get corrupted, etc.
Being able to put null keys into shared prefs, and it triggering the corruption handing code path later -- looks like a bug to me. Just my two somethings... -- K 2013/10/31 Palmer Eldritch <[email protected]>: > Why could one permit null keys - actually one null key - to have afterwards > all the preferences cleared due to an exception ? Given that the prefs are a > persistence mechanism. > No it is at least an oversight - except if I am missing something > NB - I am talking about the default shared preferences - but all shared > preferences are the same behind the scenes > > > On Wednesday, October 30, 2013 10:27:03 PM UTC+2, Kristopher Micinski wrote: >> >> I would honestly suspect that it's "meant" to be this way, and perhaps >> the documentation is buggy. If you want, posting a bug report might >> get some action by Android devs, if none of them respond here. >> >> Kris >> >> >> On Wed, Oct 30, 2013 at 3:39 PM, Palmer Eldritch <[email protected]> >> wrote: >> > I did not mean to complain at Nobu - sorry if I sounded harsh :) >> > >> > I just wanted to point out that my question was not so much what happens >> > but >> > why - and also raise awareness to this buggy and unintuitive behavior- >> > or >> > maybe have someone explain why this is so. >> > >> > Should we post a bug report ? >> > >> > >> > On Wednesday, October 30, 2013 8:23:46 PM UTC+2, Kristopher Micinski >> > wrote: >> >> >> >> Your question seems more to deal with intention rather than >> >> complaining. I believe that Nobu's response was merely interpreting >> >> the implementation and trying to interpret it, so there's no use in >> >> trying to complain at him for providing a guess at something he didn't >> >> even write. >> >> >> >> kris >> >> >> >> >> >> On Wed, Oct 30, 2013 at 2:02 PM, Palmer Eldritch <[email protected]> >> >> wrote: >> >> > >> >> > On Wednesday, October 30, 2013 7:44:17 PM UTC+2, Nobu Games wrote: >> >> >> >> >> >> I quickly peeked into the source code and well, this is the way how >> >> >> it >> >> >> is >> >> >> programmed. When an exception occurs while the preferences data file >> >> >> gets >> >> >> read, SharedPreferences sets internally an empty map so you start >> >> >> from >> >> >> scratch. I even dug a bit deeper. The XML serializer just ignores >> >> >> NULL >> >> >> keys >> >> >> and creates XML output that cannot be properly read anymore through >> >> >> the >> >> >> map >> >> >> deserialization method which seems to expect an existing key value. >> >> > >> >> > >> >> > My question is really why was it allowed to insert a null key in the >> >> > first >> >> > place - why not throw a NPE immediately (and say so in the docs) ? >> >> > If you read my links (point 3 here) you will see that null keys are >> >> > perfectly valid : - they fail only on loading the prefs - taking >> >> > down >> >> > everything with them >> >> > They should either fix deserialization or prohibit null keys >> >> >> >> >> >> >> >> >> As for why it has been programmed like that... I think the reasoning >> >> >> may >> >> >> be that preferences are not deemed to be of so much importance that >> >> >> it >> >> >> should make the app crash in case of failure. This error state is >> >> >> silently >> >> >> discarded and you start over with the defaults. I think that's a >> >> >> reasonable >> >> >> approach since any app should be able to start over with empty >> >> >> preferences. >> >> > >> >> > >> >> > >> >> > Not at all - Shared Preferences is a documented persistence mechanism >> >> > - >> >> > it >> >> > is as reasonable as deleting a database without even saying so >> >> > >> >> >> >> >> >> >> >> >> In this particular case you may have discovered a tiny bug you may >> >> >> want >> >> >> to >> >> >> report. But to be honest, using null keys is a pretty unusual thing >> >> >> to >> >> >> do. >> >> > >> >> > >> >> > Not so (either by mistake or not). >> >> > See the discussions in the SO. Some more I suspect they may have to >> >> > do >> >> > with >> >> > null keys : >> >> > >> >> > sharedpreferences - Android - Shared Preferences are lost sometimes - >> >> > Stack >> >> > Overflow >> >> > >> >> > >> >> > http://stackoverflow.com/questions/7943573/android-shared-preferences-are-lost-sometimes >> >> > android - Shared Preferences get lost after shutting down device or >> >> > killing >> >> > the app - Stack Overflow >> >> > >> >> > >> >> > http://stackoverflow.com/questions/9803838/shared-preferences-get-lost-after-shutting-down-device-or-killing-the-app#comment12495021_9803838 >> >> > >> >> >> >> >> >> >> >> >> On Wednesday, October 30, 2013 5:48:12 AM UTC-5, Palmer Eldritch >> >> >> wrote: >> >> >>> >> >> >>> The preferences are apparently cleared when one tries to load them >> >> >>> when >> >> >>> there is a null key which is bad ! Reproducer : >> >> >>> >> >> >>> public class XmlExceptionTest extends AndroidTestCase { >> >> >>> /** Run it twice - on the second run the exception is >> >> >>> thrown >> >> >>> */ >> >> >>> public void testXmlException() { >> >> >>> Context ctx = getContext(); >> >> >>> SharedPreferences prefs = PreferenceManager >> >> >>> .getDefaultSharedPreferences(ctx); // exception >> >> >>> thrown >> >> >>> here (line 18) >> >> >>> // and apparently it clears the prefs as the condition >> >> >>> below >> >> >>> is false >> >> >>> if (prefs.contains("run_once")) { // false >> >> >>> Log.w("XmlExceptionTest", >> >> >>> "contains null key :" + prefs.contains(null)); >> >> >>> } >> >> >>> Editor e = prefs.edit(); >> >> >>> e.putBoolean("run_once", true).commit(); >> >> >>> e.putString(null, "I put a sting with null >> >> >>> key").commit(); >> >> >>> assertTrue("Contains null", prefs.contains(null)); >> >> >>> PreferenceManager.getDefaultSharedPreferences(ctx); // >> >> >>> exception >> >> >>> // NOT thrown here - why ? - apparently there is a >> >> >>> static >> >> >>> factory >> >> >>> // returning the instance it already constructed >> >> >>> // e.clear().commit(); // this eliminates the exception >> >> >>> } >> >> >>> } >> >> >>> >> >> >>> exception : >> >> >>> >> >> >>> W/ApplicationContext(): getSharedPreferences >> >> >>> W/ApplicationContext(): org.xmlpull.v1.XmlPullParserException: >> >> >>> Map >> >> >>> value without name attribute: string >> >> >>> W/ApplicationContext(): at >> >> >>> >> >> >>> com.android.internal.util.XmlUtils.readThisMapXml(XmlUtils.java:521) >> >> >>> W/ApplicationContext(): at >> >> >>> >> >> >>> com.android.internal.util.XmlUtils.readThisValueXml(XmlUtils.java:733) >> >> >>> W/ApplicationContext(): at >> >> >>> com.android.internal.util.XmlUtils.readValueXml(XmlUtils.java:667) >> >> >>> W/ApplicationContext(): at >> >> >>> com.android.internal.util.XmlUtils.readMapXml(XmlUtils.java:470) >> >> >>> W/ApplicationContext(): at >> >> >>> android.app.ContextImpl.getSharedPreferences(ContextImpl.java:361) >> >> >>> W/ApplicationContext(): at >> >> >>> >> >> >>> >> >> >>> android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:348) >> >> >>> W/ApplicationContext(): at >> >> >>> >> >> >>> >> >> >>> gr.uoa.di.android.helpers.test.XmlExceptionTest.testXmlException(XmlExceptionTest.java:18) >> >> >>> W/ApplicationContext(): at >> >> >>> java.lang.reflect.Method.invokeNative(Native Method) >> >> >>> W/ApplicationContext(): at >> >> >>> java.lang.reflect.Method.invoke(Method.java:521) >> >> >>> W/ApplicationContext(): at >> >> >>> junit.framework.TestCase.runTest(TestCase.java:154) >> >> >>> W/ApplicationContext(): at >> >> >>> junit.framework.TestCase.runBare(TestCase.java:127) >> >> >>> W/ApplicationContext(): at >> >> >>> junit.framework.TestResult$1.protect(TestResult.java:106) >> >> >>> W/ApplicationContext(): at >> >> >>> junit.framework.TestResult.runProtected(TestResult.java:124) >> >> >>> W/ApplicationContext(): at >> >> >>> junit.framework.TestResult.run(TestResult.java:109) >> >> >>> W/ApplicationContext(): at >> >> >>> junit.framework.TestCase.run(TestCase.java:118) >> >> >>> W/ApplicationContext(): at >> >> >>> android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169) >> >> >>> W/ApplicationContext(): at >> >> >>> android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154) >> >> >>> W/ApplicationContext(): at >> >> >>> >> >> >>> >> >> >>> android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:520) >> >> >>> W/ApplicationContext(): at >> >> >>> >> >> >>> >> >> >>> android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447) >> >> >>> >> >> >>> Posted in SO here and in the relevant thread here - but still no >> >> >>> answers >> >> >>> >> >> >>> Any ideas ? >> >> > >> >> > -- >> > >> > -- >> > You received this message because you are subscribed to the Google >> > Groups "Android Developers" group. >> > To post to this group, send email to [email protected] >> > To unsubscribe from this group, send email to >> > [email protected] >> > For more options, visit this group at >> > http://groups.google.com/group/android-developers?hl=en >> > --- >> > You received this message because you are subscribed to the Google >> > Groups >> > "Android Developers" group. >> > To unsubscribe from this group and stop receiving emails from it, send >> > an >> > email to [email protected]. >> > For more options, visit https://groups.google.com/groups/opt_out. > > -- > You received this message because you are subscribed to the Google > Groups "Android Developers" group. > To post to this group, send email to [email protected] > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Android Developers" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/groups/opt_out. -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en --- You received this message because you are subscribed to the Google Groups "Android Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.

