Как принудительно перезапустить службу?

У меня есть фоновый сервис, который иногда убивается ОС, когда он работает с низким объемом памяти.

  • Как имитировать такое поведение, чтобы я мог его отлаживать?

В руководстве dev просто говорится: "Если ваша служба запущена, тогда вы должны ее разработать, чтобы изящно обрабатывать перезагрузки системой. Если система убивает вашу службу, она перезапускает ее, как только ресурсы становятся доступными снова".

  1. Какова последовательность вызовов с момента ее завершения до завершения перезапуска?

Что касается вопроса о том, что происходит с активным запуском AsyncTask, запущенным в сервисе, когда служба была убита операционной системой, то есть без вызова service.onDestroy? Поддерживает ли он работу или получает разорванную паузу вместе со службой?

Ответы

Ответ 1

В более новых версиях служба будет иметь следующие события:

onCreate()

Далее следуют...

int onStartCommand(Intent intent, int flags, int startid)

Я знаю, что в комментариях выше вы упоминаете об использовании этого, но стоит повторить: Не используйте старое событие onStart(). onStartCommand - это новый способ делать вещи.

onCreate() может использоваться для создания любых объектов и т.д., но на самом деле код вашего сервиса в onStartCommand().

Когда вы закончите с onStartCommand(), вы должны вернуть результат. Использование "START_STICKY" сообщает операционной системе, что он может перезагрузиться, если ему нужно его убить. Использование "START_NOT_STICKY" сообщает os, чтобы не пытаться перезапустить его после того, как память снова станет доступной. Это означает, что вашему приложению потребуется снова запустить службу вручную. Существуют и другие варианты - проверьте документы API.

Проверка этих флагов позволит вам узнать, почему ваша служба запустила, если ваше собственное приложение запустило его или если ОС запустило его для его перезапуска. Вам нужно будет периодически сохранять состояние любых важных переменных, чтобы, если ОС перезапустила его, вы можете получить их - вы, вероятно, можете использовать личное хранилище SharedPreferences для их хранения. Определенно сохраняйте любое событие onDestroy, но не рассчитывайте на то, что он вызван.

Кроме того, рекомендуется сохранить поле startID в переменной и использовать его с stopSelfResult (startId), когда ваша служба будет запущена.

Имейте в виду, что если ваша служба была убита операционной системой, у вас может не быть возможности хранить какие-либо переменные.. Вы должны уметь видеть, находится ли ваше состояние в ожидании при перезапуске ОС и если не просто reset все или умело умереть, возможно.

Что касается отладки, считаете ли вы, что вы пишете другое приложение, которое ничего не делает, кроме сосать память в Activity для того, чтобы заставить условие низкой памяти? Верхняя активность должна отдавать предпочтение памяти и заставлять службу умирать.

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

Что-то еще, что может быть полезно для вас, - проверить, запущен ли ваш сервис из вашего приложения. Здесь функция для этого:

// Determine if one of my services is currently running
public static boolean isMyServiceRunning(Context context, String servicename) {
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        if (servicename.equals(service.service.getClassName())) {
            return true;
        }
    }
    return false;
}

Ответ 2

Если это локальная служба (по умолчанию), а не удаленная служба, она работает в том же процессе, что и ваше приложение. Это означает, что вы можете эмулировать убийство, просто убивая процесс своего приложения. Вы можете сделать это с помощью ddms, например, в eclipse или из командной строки или даже с вашего телефона (настройки → приложения).