Фоновая служба Android перезагружается, когда приложение убито
Я разрабатываю приложение, в котором создается фоновая служба для сбора данных датчиков. Я запускаю службу из своей деятельности:
startService(new Intent(this, MyService.class));
Я создал службу, поэтому, если приложение уничтожено, фоновая служба по-прежнему продолжает собирать данные. Я пробовал это, и это работало в определенной степени. Моя проблема в том, что когда я убиваю приложение, служба, похоже, перезапускается, потому что вызывается метод onCreate()
и onStart()
. Есть ли способ, с помощью которого служба не перезагружается, пожалуйста?
UPDATE:
Как было предложено в ответе ниже, я добавил следующий метод в службу, но не повезло.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Ответы
Ответ 1
Это зависит от значения, возвращаемого в onStartCommand.
Вы должны вернуть START_NOT_STICKY
В соответствии с документация:
Для запущенных служб есть два дополнительных основных режима работы, которые они могут решить, в зависимости от значения, которое они возвращают из onStartCommand(): START_STICKY используется для служб, которые явно запускаются и останавливаются по мере необходимости, в то время как START_NOT_STICKY или START_REDELIVER_INTENT используются для служб, которые должны работать только при обработке любых команд, отправленных им.
Вкратце:
Если вы вернете START_STICKY, служба будет восстановлена всякий раз, когда будут доступны ресурсы. Если вы вернете START_NOT_STICKY, вам необходимо повторно активировать услугу, отправляющую новое намерение.
Поскольку все это вызвало мое любопытство, я сделал пример приложения, чтобы проверить это. Вы можете найти zip со всеми источниками здесь
Есть кнопка startService и кнопка stopService, которые делают то, что вы ожидаете от них.
Служба возвращает START_NOT_STICKY в onStartCommand.
Я поместил тосты в onCreate, onStartCommand и onDestroy.
Вот что происходит:
- Если я нажимаю start, onCreate и onStart вызываются
- Если я нажимаю стоп, срабатывает onDestroy
- Если я дважды нажимаю кнопку, onCreate вызывается один раз и onStartCommand дважды
Таким образом, он ведет себя так, как можно было бы ожидать.
Если я запустил службу и убью приложение, как вы описали, onDestroy не будет вызван, но ни onCreate, ни onStart.
Если я вернусь к приложению и снова нажму, onCreate будет вызван, что означает, что, как я писал ранее, START_NOT_STICKY предотвращает автоматический перезапуск службы.
Я думаю, у вас есть что-то еще в вашем приложении, которое снова запускает службу (возможно, ожидающее намерения).
Ответ 2
Приложение и служба живут в одном процессе, что означает, что приложение убито, так что это ваша служба. Изменение возвращаемого значения onStartCommand не влияет на этот процесс. Он просто сообщает службе либо начать/остановить, когда вы сообщите об этом, либо когда он закончит делать то, что ему нужно. Как уже упоминалось в вашем комментарии к исходному сообщению, настройка его как процесса переднего плана работала, но это действительно просто заставляло службу иметь высокий приоритет, а не решение проблемы.
Чтобы изменить Сервис, чтобы он был убит отдельно и считал его запущенной службой, а не связанной службой из-за использования onStartCommand, укажите имя процесса в манифесте для этой Службы.
В Руководство по разработке процессов и потоков:
Запись манифеста для каждого типа компонентного элемента - <activity>, <service>, <receiver>, and <provider>
- поддерживает атрибут android: process, который может указывать процесс, в котором этот компонент должен работать. Вы можете установить это атрибут, чтобы каждый компонент работал в своем собственном процессе или так что некоторые компоненты совместно используют процесс, в то время как другие - нет. Вы также можете настроить android: process, чтобы компоненты разных приложений работают в одном и том же процесса, при условии, что приложения используют один и тот же Идентификатор пользователя Linux и подписан с теми же сертификатами.
Android может решить закрыть процесс на некоторых точка, когда память низкая и требуется другим процессы, которые более немедленно обслуживают пользователя. Компоненты приложения, работающие в процессе, который убиты, следовательно, уничтожены. Начат процесс снова для тех компонентов, когда они снова работают для них.
Из <service>
в файле манифеста:
Android: процесс
Название процесса, в котором должна выполняться служба. Обычно все компоненты приложения выполняются в процессе по умолчанию созданный для приложения. Он имеет то же имя, что и приложение пакет. Атрибут процесса элемента может установить по умолчанию для всех компонентов. Но компонент может переопределить по умолчанию с собственным атрибутом процесса, что позволяет приложения на нескольких процессах.
Если имя, присвоенное этому атрибут начинается с двоеточия (':'), новый процесс, частный для приложение, создается, когда это необходимо, и служба работает в этом обработать. Если имя процесса начинается с символа в нижнем регистре, служба будет выполняться в глобальном процессе с таким именем при условии, что это имеет разрешение на это. Это позволяет использовать компоненты в разных приложений для совместного использования процесса, сокращения использования ресурсов.
Не знаю, почему был проголосован другой ответ, который упоминал об этом. Я использовал этот метод в прошлом и сегодня создал простое приложение Activity с сервисом в другом процессе, чтобы убедиться, что я не сумасшедший. Я использовал Android Device Monitor, чтобы убить процесс приложения. Вы можете видеть как отдельные процессы в ADM, так и видеть, что когда процесс приложения убит, Служба не работает.
Ответ 3
Если вы используете IntentService, он имеет
onHandleIntent()
где вы должны поместить код, который необходимо выполнить. Он выполняется в отдельном потоке (а не в потоке пользовательского интерфейса, где выполняется ваше приложение), поэтому ваше приложение не должно влиять на него. Когда код завершит выполнение, поток прекратится и служба автоматически остановится.
Ответ 4
Я знаю, что очень поздно ответить на этот вопрос, но может быть, это может быть полезно другим. Это действительно помогло мне в моем приложении Music Player.
Если есть службы, которые могут быть разрушительными или могут повлиять на работу пользователя, например музыку и т.д., тогда в этом случае вам необходимо использовать уведомление и когда сервис будет запущен успешно, затем создайте уведомление и используйте функцию
startForeground(int Notification_id,Notification);
Это запустит вашу службу в фоновом режиме без перезапуска и повторного использования ее методов.
https://developer.android.com/reference/android/app/Service.html
Ответ 5
Старт не липкий, не работает над kitkat, а другой onTaskRemoved не работает над Marshmellow.
onTaskRemoved может использоваться с помощью некоторых исключений. Не работал над этим. Но попробуйте это.
Ответ 6
Когда память низкая, автоматически запускается служба, работающая в фоновом режиме. Вместо того, чтобы использовать startService() для запуска службы, попробуйте вместо этого использовать StartForeground(). Служба работает на переднем плане и никогда не будет убита, даже если память низкая.
Ответ 7
Я столкнулся с той же проблемой и смог ее разрешить, запустив службу в глобальном процессе. Вы делаете это, добавляя в тег манифеста следующее:
процесс = "com.myapp.ProcessName"
(Составьте любое имя.)
Когда я это сделал, я обнаружил, что моя служба не была убита (и перезапущена), когда приложение вычищено из списка. Предположительно, это связано с тем, что процесс приложения убивается, когда вы его удаляете, но глобальные сервисные процессы не являются.
Недостатком этого является то, что связь между вашим приложением и сервисом теперь должна осуществляться через интерфейс IBinder; вы не можете напрямую вызывать функции в приложении или службе из другого, потому что они работают в разных процессах.