SharedPreferences は結構簡単に壊れる
ちょっと前に Google+ に書いたけど、こっちにも。
Android開発者が大好きで信頼も厚い SharedPreferences が、意外と簡単に壊れる件。
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); Editor editor = prefs.edit(); editor.putString("name", "\0"); // ←ここが問題の箇所 editor.commit();
このようにすると、次回 SharedPreferences を読み込むときにログに warning が出力され、保存したデータはすべて失われてしまいます。
W/ApplicationContext( 4239): getSharedPreferences W/ApplicationContext( 4239): org.xmlpull.v1.XmlPullParserException: Error parsing document. (position:line -1, column -1) caused by: org.apache.harmony.xml.ExpatParser$ParseException: At line 3, column 20: not well-formed (invalid token) W/ApplicationContext( 4239): at org.apache.harmony.xml.ExpatPullParser$ByteDocument.flush(ExpatPullParser.java:958) W/ApplicationContext( 4239): at org.apache.harmony.xml.ExpatPullParser$Document.pump(ExpatPullParser.java:769) W/ApplicationContext( 4239): at org.apache.harmony.xml.ExpatPullParser$Document.dequeue(ExpatPullParser.java:813) W/ApplicationContext( 4239): at org.apache.harmony.xml.ExpatPullParser.next(ExpatPullParser.java:302) W/ApplicationContext( 4239): at com.android.internal.util.XmlUtils.readValueXml(XmlUtils.java:675) W/ApplicationContext( 4239): at com.android.internal.util.XmlUtils.readMapXml(XmlUtils.java:470) W/ApplicationContext( 4239): at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:379) W/ApplicationContext( 4239): at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:146) W/ApplicationContext( 4239): at android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:348) W/ApplicationContext( 4239): at jp.syoboi.test.helloworld.HelloWorldActivity.onCreate(HelloWorldActivity.java:16) W/ApplicationContext( 4239): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) W/ApplicationContext( 4239): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611) W/ApplicationContext( 4239): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663) W/ApplicationContext( 4239): at android.app.ActivityThread.access$1500(ActivityThread.java:117) W/ApplicationContext( 4239): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931) W/ApplicationContext( 4239): at android.os.Handler.dispatchMessage(Handler.java:99) W/ApplicationContext( 4239): at android.os.Looper.loop(Looper.java:130) W/ApplicationContext( 4239): at android.app.ActivityThread.main(ActivityThread.java:3683) W/ApplicationContext( 4239): at java.lang.reflect.Method.invokeNative(Native Method) W/ApplicationContext( 4239): at java.lang.reflect.Method.invoke(Method.java:507) W/ApplicationContext( 4239): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) W/ApplicationContext( 4239): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) W/ApplicationContext( 4239): at dalvik.system.NativeStart.main(Native Method)
「設定が初期化される」という問題が報告され「あぁ、また Galaxy S か」と思っていたところ、この問題が見つかりました。
実際には Exception のメッセージをそのまま SharedPreferences に保存していたら、たまたまその中に "\uffff" が含まれていて、SharedPreferences が壊れていたというわけでした。こわいこわい。