Подтвердить что ты не робот

Фоновая служба Android перезагружается, когда приложение убито

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

startService(new Intent(this, MyService.class));

Я создал службу, поэтому, если приложение уничтожено, фоновая служба по-прежнему продолжает собирать данные. Я пробовал это, и это работало в определенной степени. Моя проблема в том, что когда я убиваю приложение, служба, похоже, перезапускается, потому что вызывается метод onCreate() и onStart(). Есть ли способ, с помощью которого служба не перезагружается, пожалуйста?

UPDATE:

Как было предложено в ответе ниже, я добавил следующий метод в службу, но не повезло.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_NOT_STICKY;
}
4b9b3361

Ответ 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; вы не можете напрямую вызывать функции в приложении или службе из другого, потому что они работают в разных процессах.