Проблемы с поддержанием службы в рабочем состоянии из-за поворота, уничтожения при выходе из приложения и выключения экрана в альбомной ориентации

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

1) Служба должна работать, пока приложение находится на переднем плане.

2) Когда активность вращается, не останавливайте службу

3) Служба должна оставаться активной, даже если вы сворачиваете приложение, когда открыт один конкретный фрагмент.

4) Когда действие остановлено (не с помощью поворота) и это не конкретный фрагмент, остановите службу.

Я запускаю/останавливаю свои службы в файле onstart/onstop. В итоге я использовал логическое значение, чтобы отслеживать, вращается ли экран.

Я запускаю/останавливаю свои услуги следующим образом

context.getApplicationContext().startService(намерение)

context.getApplicationContext().stopService(намерение)

Все работало отлично, за исключением одного случая.

Когда вы выключаете экран в альбомной ориентации, Android по какой-то причине решает, что ему нужно воссоздать всю активность, и вызывает через весь жизненный цикл. Я воспроизвел это в базовом приложении на 4.4 и 5.0.1, и это было показано в других темах, таких как эта.

Проблемы с пониманием жизненного цикла, когда экран выключается и на

Когда это происходит, нельзя полагаться на вращение/не вращение, и я предполагаю, что из-за того, как быстро все происходило (несколько onStop/onStarts), это вызывало состояние гонки. Когда я возвращался в приложение, иногда оно работало, иногда зависало (ошибок не было), иногда работали две службы.

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

Один поток предложил использовать безголовый фрагмент, чтобы он выжил при вращении, но мне все еще нужно, чтобы он останавливался, когда приложение закрывается, поэтому я в конечном итоге застрял с той же проблемой.

Есть ли рекомендуемые способы решения этой проблемы? Нельзя допустить, чтобы служба оставалась активной, если приложение закрыто (за исключением фрагмента 1), это просто приведет к огромной разрядке батареи, и ей нужно пережить ротацию, иначе она будет прерывать работу.




Ответы (1)


Зачем использовать службу, если вам не нужно, чтобы она работала, когда приложение закрыто? Просто запустите фоновый поток при запуске приложения и выполняйте там свою работу.

ОБНОВЛЕНИЕ: вместо того, чтобы запускать свою службу из действия, вы можете запустить ее из своего класса приложения (или его потомка). Вы можете остановить его, когда ваше приложение перейдет в фоновый режим или будет уничтожено, а затем запустить его снова, если приложение будет возобновлено.

Наиболее распространенный способ сделать это — отслеживать, сколько действий в настоящее время находится в состоянии возобновления. Это означает, что в onPause() и onResume() каждой Activity вы уменьшаете или увеличиваете этот счетчик. Если счетчик равен 0, вы знаете, что ваше приложение работает в фоновом режиме. Примечание: вы, вероятно, захотите добавить задержку для уменьшения счетчика в onPause(), поскольку, конечно, будут моменты, когда вы переходите от одного действия к другому (или меняете ориентацию), когда действие A будет приостановлено до начала действия B.

person Karim Varela    schedule 23.03.2015
comment
Это сторонняя библиотека, которая работает с некоторым оборудованием через Bluetooth. Служба осуществляет связь с оборудованием, и на одном конкретном фрагменте она должна оставаться активной. Он используется и в других фрагментах, но ничего страшного, если он будет отключен на этих экранах. - person Ben987654; 24.03.2015
comment
Но как бы я его отключил? Насколько я понимаю, жизненного цикла приложения нет, есть только действия. Использование Application.ActivityLifecycleCallbacks по-прежнему будет запускаться из жизненного цикла активности, и я столкнусь с той же проблемой, когда выключу экран в ландшафтном режиме? - person Ben987654; 24.03.2015
comment
Да, это не идеально. Наиболее распространенный способ сделать это — отслеживать, сколько действий в настоящее время находится в состоянии возобновления. Это означает, что в каждом Activity onPause() и onResume() вы уменьшаете или увеличиваете этот счетчик. Если счетчик равен 0, вы знаете, что ваше приложение работает в фоновом режиме. Примечание: вы, вероятно, захотите добавить задержку для уменьшения счетчика в onPause(), поскольку, конечно, будут моменты, когда вы переходите от одного действия к другому (или меняете ориентацию), когда действие A будет приостановлено до начала действия B. - person Karim Varela; 24.03.2015
comment
Хорошо, я попробую и отчитаюсь. Спасибо! - person Ben987654; 24.03.2015
comment
Похоже, это может работать, мне пришлось использовать задержку в 600 мс, иначе я все равно получил бы какое-то странное поведение с выключенным ландшафтным экраном. Завтра проведу еще несколько тестов, чтобы убедиться, что все в порядке. - person Ben987654; 24.03.2015
comment
Сейчас это работает хорошо. Основным исправлением на самом деле был ваш комментарий о подсчете возобновленных действий и, в частности, о задержке, иначе у меня все еще была та же проблема. Вы хотите обновить ответ с этим комментарием или я могу отметить родительский ответ как правильный? - person Ben987654; 24.03.2015
comment
Добавление задержек к логике должно быть нарушением T&C stackoverflow. - person Fen1kz; 15.06.2016