SharedPreferences not stored after appl is stopped


  1. lightningRay

    lightningRay Member

    My first android application has to do with showing activities at different times. All works fine ... except that when I retrieve the shared preferences in an activity activated from the notification manager, all my options are reset to default values.

    Similarly, when I try to reinstall an alarm after the phone is switched off, all the previously stored shared preferences options are non-existent.

    Is there something special that has to be set in the manifest, or do I have to retrieve the context in a special manner? from a broadcastReceiver?

    Advertisement
    :
  2. lightningRay

    lightningRay Member

    No replies ?!

    In particular, if I go to [Android Settings | Manage Applications ] and force-close my application, the SharedPreferences are lost.

    WHY!?!?

    I thought that SharedPreferences is permanent storage.

    BTW, I'm following Chapter 6 of "Professional Android 2 Application Development".
  3. alostpacket

    alostpacket Over Macho Grande? VIP Member

    welcome to AF!

    Dont forget to commit your edit with

    yourSharedPrefsEditorObject.commit();

    otherwise they will be lost. I tend to commit the edit any time i change a pref

    hth
  4. lightningRay

    lightningRay Member

    Thanks alostpacket ...

    I do .commit() after setting new values. It seems to me that I must be missing something incredibly obvious because the values in sharedPreferences should remain after the application is force-closed.

    Here is a snippet of my code:

    ------------>< snip ><---------------

    public class SetupActivity extends Activity {

    public static final String PREFS = "SelfExpPrefs";

    // keys
    public static final String NOTBEFORE = "NotBefore";
    public static final String NOTAFTER = "NotAfter";
    public static final String PINGSOUND = "PingSound";

    //Preferences that the user can set
    private long notBeforeMillis = 0l;
    private long notAfterMillis = 0l;
    private String pingSound = (String)null;

    SharedPreferences settings;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.setup);

    settings = getSharedPreferences(PREFS, Context.MODE_PRIVATE);

    notBeforeMillis = settings.getLong(NOTBEFORE,
    8 * 60 * 60 * 1000);
    notAfterMillis = settings.getLong(NOTAFTER,
    20 * 60 * 60 * 1000);
    pingSound = settings.getString(PINGSOUND, (String)null);

    // SNIP SNIP

    Button doSetup = (Button) findViewById(R.id.buttonSetup);
    doSetup.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View arg0) {
    // save the shared preferences
    settings = getSharedPreferences(PREFS, Context.MODE_PRIVATE);

    SharedPreferences.Editor settingsEdit = settings.edit();
    settingsEdit.putLong(NOTBEFORE, notBeforeMillis);
    settingsEdit.putLong(NOTAFTER, notAfterMillis);
    settingsEdit.putString(PINGSOUND, pingSound);
    settingsEdit.commit();

    finish();
    }
    });

    } // onCreate

    } // class SetupActivity
  5. alostpacket

    alostpacket Over Macho Grande? VIP Member

    I take it the values change in the "// SNIP SNIP" part? :)

    I'm also a bit suprised it let you compile this part:
    Code (Text):
    1.  
    2. doSetup.setOnClickListener(new View.OnClickListener()
    3. {
    4.             @Override
    5.             public void onClick(View arg0)
    6.             {
    7.                 // save the shared preferences    
    8.                 settings = getSharedPreferences(PREFS, Context.MODE_PRIVATE);
    9. ...
    10.  
    11.  
    getSharedPreferences() is not a method of View.OnClickListener, rather it's a method of Context/ContextWrapper/Activity
  6. lightningRay

    lightningRay Member

    > I take it the values change in the "// SNIP SNIP" part?

    Yes, I have 3 buttons to bring up 3 Dialogs that set the 3 parameters. I can debug the code and I see that the 3 values are correctly changed.

    > I'm also a bit suprised it let you compile this part:
    > ...
    > getSharedPreferences() is not a method of View.OnClickListener,
    > rather it's a method of Context/ContextWrapper/Activity

    It definitely compiles .. I copy/pasted directly from the source files in Eclipse (Helios).

    Could this be the problem? Would I issue the call like:

    Context context = getApplicationContext();
    settings = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE);

    MORE ...

    I tried the above code and it doesn't solve the problem.

    I found the following on the Android Reference doc <http://developer.android.com/reference/android/content/Context.html#getApplicationContext()>

    ------------>< snip ><------------------

    public abstract Context getApplicationContext ()

    Since: API Level 1
    Return the context of the single, global Application object of the current process. This generally should only be used if you need a Context whose lifecycle is separate from the current context, that is tied to the lifetime of the process rather than the current component. Consider for example how this interacts with registerReceiver(BroadcastReceiver, IntentFilter):

    If used from an Activity context, the receiver is being registered within that activity. This means that you are expected to unregister before the activity is done being destroyed; in fact if you do not do so, the framework will clean up your leaked registration as it removes the activity and log an error. Thus, if you use the Activity context to register a receiver that is static (global to the process, not associated with an Activity instance) then that registration will be removed on you at whatever point the activity you used is destroyed.

    -------------->< snip ><-------------

    What does this entail? Could this be related to my sharedPreferences not being saved when my application is force-closed?

    What would be the solution?
  7. lightningRay

    lightningRay Member

    Now I'm really confused!

    I wrote my parameters out to a file, using FileWriter(), and when I force-close my application, my test file has disappeared!

    Why is force-closing removing everything to do with my application?

    I only force-close the application; I don't "remove" its data.
  8. alostpacket

    alostpacket Over Macho Grande? VIP Member

    That's one correct way to call it, yes. You should have this code as a class variable though:

    Code (Text):
    1. public class MyClass extends Activity
    2. {
    3.  
    4.          protected Context appContext= null;
    5.  
    6.          @Override
    7.          public void onCreate( Bundle savedInstanceState )
    8.          {
    9.                  super.onCreate(savedInstanceState);
    10.                  appContext = getApplicationContext();
    11.          }
    12.  
    13.  
    14. //then in your listener onClick you can use appContext.getSharedPreferences()
    15.  
    16. }
    I'm not sure why things arent working otherwise. Are you using a Preference activity?

    For the file writer, are you closing the file output stream?

    Anyways, you seem to have a good understanding of how things are supposed to work, so maybe the bug lies elsewhere in some obscure place where you wrote = instead of == (as an example). Basically I'm saying things seem to be in order, so it might be worth pouring over the whole code/class to see.

    Also, are you doing this on the emulator or on a phone? Have you created an SD card/storage space for you emulated device if you are?

    Maybe try creating a button to test the preferences were saved correctly?

    Anyways, these are just some possible places to start but I feel your pain, we've all been there where everything seems to make no sense :) hang in there, it gets better ;)
  9. lightningRay

    lightningRay Member

    Thanks, I'll use this tid-bit. :)

    No, I am not using Preference Activity, and yes I do .close() the file stream.

    I am running the application directly on my HTC desire.

    I can run the application several times and I see that my changed preferences are stored correctly between each invocation (on the handset). However, the issue arises when I force-close the application from the Android Application setup menu. After this, when I invoke the application again, it starts up with default values and not the values I had previously set and stored in the sharedPreferences.

    Could it have to do with something in the Manifest?

    I use an Application class (for singleton variables) and I have 2 Receivers (one triggered by an alarm notification, and one triggered by turning on the handset).
  10. alostpacket

    alostpacket Over Macho Grande? VIP Member

    Yeah, might be something where you set it back to default when reading it in or something, I know I had a bug like that awhile back. Took me forever to realize where I was making the mistake hehe.

    One thing to check:

    Make sure when you read the variables you are using the exact same names/context.

    You can test this by changing the default read value each time you read it to see if one of the reads is actually setting the preference.

    Other than that I don't know.
  11. Jakar217

    Jakar217 New Member

  12. lightningRay

    lightningRay Member

    Hi alostpacket and Jakar217-

    Thanks for your replies. After Many hours, I isolated the problem down to a single code segment.

    Essentially, I read in a string of characters that are stored in res/raw/id.txt. I want to save the string into SharedPreferences so that I don't have to read the file every time my app runs.

    public class SetupActivity extends Activity {
    private String IDstr = (String)null;

    // ... onCreate() {

    try {
    byte[] IDbuff = new byte[80];
    int numBytes = 0;
    InputStream inID = getResources().openRawResource(R.raw.id);
    numBytes = inID.read(IDbuff);

    // SHAREDPREFERENCES ARE DELETED WHEN APP IS LATER CLOSED
    IDstr = new String(IDbuff);

    // INSTEAD, THIS FIXES THE PROBLEM
    IDstr = (new String(IDbuff)).substring(0, numBytes);;

    inID.close();
    } catch (IOException e) {
    e.printStackTrace();
    }

    // .... rest of code continues

    Note that for the SharedPreferences to be maintained, I explicitly have to extract a substring of the correct number of bytes from the String() representation of the input buffer.

    Apparently, without using substring(), the full 80 bytes from the buffer (which are initialised to 0) are stored into SharedPreferences, even when "inID.read(IDbuff);" only reads the 20 or 40 characters that are in id.txt.

    I filed a bug report on this matter.
  13. yacekm

    yacekm New Member

    See my answer on StackOverflow

    Try clearing your editor before using it. In other words do:

    Editor editor = preferences.edit();
    editor.clear();
    editor.putInt("incommingPhone", incomming);
    editor.commit();

    I have had exactly same problem like yours and this worked for me. For my whole code sample see this post on my blog
Loading...

Share This Page