15

I have been reading the Android documentation and I am wondering if anyone can shed some light on what happens to a service instance when a service started with START_STICKY has it's process killed. I am assuming that the local state data (instance variables) are also lost. Does Android do anything to help re-populate the local state when it recreates the service?

I had some data that was sent to the service in an intent. In onStateCommand(), I would populate the service's instance data based on what was in the intent. From what I have read in the Android docs, the intent passed to onStartCommand() will be null when the service has been killed and restarted (with START_STICKY). Does this mean that I lose both the intent and the service's member data when the service is recreated?

4 Answers 4

17

When a process is killed and recreated, it goes through the entire lifecycle again (starting at onCreate). Depending on how it was killed and how you save data it may or may not be available to you.

As for getting the intent back, there's a flag for START_REDELIVER_INTENT that will redeliver the intent.

4
  • Thanks for confirming my suspicions. I did not know about START_REDLIVER_INTENT (must have glossed over that part of the docs).
    – adstro
    Commented Oct 19, 2010 at 1:18
  • Thanks man, I was sacked by this bug for almost a month... Finally found out Android OS killed the service...
    – macio.Jun
    Commented Sep 3, 2015 at 17:37
  • Nice. I never knew about START_REDELIVER_INTENT, it sure came in handy @Falmarri
    – Phil
    Commented Jul 31, 2016 at 0:14
  • ok. if START_REDELIVER_INTENT delivers the old intent, what about if we created a handler to stop the service after 10mins? is that handler will not execute?
    – Mohd Qasim
    Commented May 25, 2023 at 12:16
2

I recently came across this same problem. Service provides no built in means of saving state and the last intent may not be enough to get the service back to its previous state. My solution was to have the activity persist state and pass that state to the service via startService(). The service then just fires events at the activity, like:

  • here's an update
  • something died and here's the exception
  • I've been killed, please restart me with any necessary state

This approach cleaned up my design a lot, and both service and activity are resilient to being killed.

1
  • 2
    Can u share some piece of codes for the same.. ?? The concept looks ideal , but cant implement it Commented Sep 27, 2012 at 10:55
1

Android will not re-populate 'lost' data values when it re-starts your service so your code needs to cater for this eventuality.

My approach is to use all non-primitive state variables and to leave them as null. That way I can test for null and take appropriate steps to initialise them as and when.

I have taken to storing lightweight data that I want to persist across application restarts in the application's preferences.

1

use Internal Storage for Saving object or its field individually.

public void writeToInternalStorage(String fileName,String userName)
    {
        try{
            String endOfLine = System.getProperty("line.separator");
            StringBuffer buffer = new StringBuffer();

            FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE); //// MODE_PRIVATE will create the file (or replace a file of the same name) and make it private to your application. Other modes available are: MODE_APPEND, MODE_WORLD_READABLE, and MODE_WORLD_WRITEABLE.

            buffer.append(userName.toString() + endOfLine);
            fos.write(buffer.toString().getBytes());


            Log.v(TAG, "writeFileToInternalStorage complete..  " + buffer.toString());
            //      writer.write(userName);

            fos.close();
        }
        catch(Exception e)
        {
            Log.v(TAG, "Error: " + e.getMessage());
            ExceptionNotificationMessage("writeToInternalStorage() Error: " + e.getMessage());
        }
    }

    public String readFromInternalStorage(String fileName)
    {
        try{
            File file = this.getFileStreamPath(fileName);
            if(file.exists() == true)
            {
                Log.v(TAG, "readFileFromInternalStorage File found...");    

                FileInputStream fis = openFileInput(fileName);  
                StringBuilder buffer = new StringBuilder();             
                int ch;
                while( (ch = fis.read()) != -1){
                    buffer.append((char)ch);
                }

                Log.v(TAG, "readFileFromInternalStorage complete.. " + buffer.toString());
                fis.close();

                return buffer.toString();
            }
        }
        catch(Exception e)
        {
            Log.v(TAG, "Error: " + e.getMessage());
            ExceptionNotificationMessage("readFromInternalStorage() Error: " + e.getMessage());
        }
        return "";
    }

Not the answer you're looking for? Browse other questions tagged or ask your own question.