OnStartCommand после того, как сервисный процесс убит при запуске с помощью START_STICKY

Я читал документацию на Android, и мне интересно, может ли кто-нибудь пролить свет на то, что происходит с экземпляром службы, когда служба запускалась с START_STICKY, и процесс был убит. Я предполагаю, что данные локального состояния (переменные экземпляра) также теряются. Поддерживает ли Android что-либо, чтобы помочь повторно заполнить локальное состояние при его воссоздании?

У меня были некоторые данные, которые были отправлены на службу с намерением. В onStateCommand() я бы заполнил данные экземпляра службы на основе того, что было в намерении. Из того, что я прочитал в документах Android, намерение, переданное onStartCommand(), будет равно null, когда служба была убита и перезапущена (с START_STICKY). Означает ли это, что я теряю как данные о намерениях, так и данные службы, когда служба воссоздана?

Ответ 1

Когда процесс убивается и воссоздается, он снова проходит весь жизненный цикл (начиная с onCreate). В зависимости от того, как он был убит и как вы сохраняете данные, он может быть или не быть доступен вам.

Что касается получения намерения назад, там будет флаг START_REDELIVER_INTENT, который будет переназначать намерение.

Ответ 2

Недавно я столкнулся с этой проблемой. Служба не предоставляет встроенные средства сохранения состояния, и последнее намерение может оказаться недостаточным для возврата службы в прежнее состояние. Мое решение состояло в том, чтобы сохранить состояние активности и передать это состояние службе через startService(). Затем служба просто запускает события в активности, например:

  • здесь обновление
  • что-то умерло, и здесь исключение
  • Я был убит, пожалуйста, перезапустите меня в любом состоянии.

Этот подход значительно упростил мой дизайн, и как сервис, так и активность являются гибкими, чтобы быть убитыми.

Ответ 3

Android не будет повторно заполнять "потерянные" значения данных при повторном запуске службы, чтобы ваш код нуждался в этом случае.

Мой подход - использовать все не примитивные переменные состояния и оставить их как null. Таким образом, я могу проверить значение null и предпринять соответствующие шаги для их инициализации как и когда.

Я взял на хранение легкие данные, которые я хочу сохранить на перезапуске приложений в настройках приложения.

Ответ 4

используйте внутреннее хранилище для сохранения объекта или его поля отдельно.

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 "";
    }