Устранение неполадок с активными службами

В этой статье описаны распространенные причины сбоев в работе активных служб и способы их устранения.

В этом документе рассматриваются следующие проблемы:

Перед устранением неполадок

Проверьте недавние изменения в активных службах

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

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

  • Код активной службы, который раньше работал, теперь не работает
  • Вы только начали тестирование новой версии платформы или изменили целевой уровень API для приложения.

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

Ошибки ANR ("Приложение не отвечает")

В некоторых случаях приложение должно отключать активную службу. Если приложение не остановит сервис, это сделает система, и возникнет ошибка Приложение не отвечает (ANR).

Короткий сервис работает слишком долго, вызывая ошибку ANR

Активные службы типа shortService должны быстро завершать работу – примерно в течение трех минут. Когда время истекает, система вызывает метод Service.onTimeout(int,int) сервиса. У сервиса есть несколько секунд, чтобы вызвать stopSelf(). Если сервис не останавливается самостоятельно, система выдает ошибку "Приложение не отвечает".

Диагностика

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

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"

Решение

Убедитесь, что все активные службы с ограниченным временем работы завершают работу и вызывают метод stopForeground(int) в течение системного ограничения по времени.

Реализуйте Service.onTimeout(int,int) в активных службах. Убедитесь, что ваша реализация этого метода сразу вызывает stopSelf().

Исключения для активных служб

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

В некоторых случаях система выдает внутреннее исключение. В таких случаях вы можете узнать, что это за исключение, посмотрев трассировку стека, а также проверить Logcat, чтобы получить более подробную информацию об ошибке.

Внутреннее исключение: превышено время ожидания.

Система ограничивает время работы активных служб синхронизации данных и обработки медиаконтента, когда приложение находится в фоновом режиме. Если сервис превышает этот лимит, система вызывает метод Service.onTimeout(int,int) сервиса. У сервиса есть несколько секунд, чтобы вызвать stopSelf(). Если сервис не остановится сам, система сгенерирует внутреннюю ошибку RemoteServiceException, что приведет к сбою приложения.

Диагностика

Чтобы узнать, какое исключение возникло, посмотрите трассировку стека. Более подробную информацию об ошибке можно найти в Logcat. В этом случае в Logcat появится следующее сообщение об ошибке:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"

Решение

Убедитесь, что все активные службы с ограниченным временем работы завершают работу и вызывают stopForeground(int) в пределах системного ограничения по времени.

Реализуйте Service.onTimeout(int,int) в активных службах. Убедитесь, что ваша реализация этого метода сразу вызывает stopSelf().

Внутреннее исключение: ForegroundServiceDidNotStartInTimeException

Когда вы запускаете службу, вызывая context.startForegroundService(), у этой службы есть несколько секунд, чтобы стать активной службой, вызвав ServiceCompat.startForeground(). Если сервис этого не делает, выдается внутренняя ошибка ForegroundServiceDidNotStartInTimeException.

Диагностика

Чтобы узнать, какое исключение возникло, посмотрите трассировку стека. Более подробную информацию об ошибке можно найти в Logcat. В этом случае в Logcat появится следующее сообщение об ошибке:

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()

Решение

Убедитесь, что все новые активные службы вызывают ServiceCompat.startForeground() в течение нескольких секунд.

WorkManager:

Это исключение также может возникать при работе с WorkManager, которые выполняют активную службу (вызывают setForegound или setForegroundAsync). Если жизненные циклы двух активных рабочих процессов пересекаются, когда один из них пытается запустить активную службу, а другой – завершить ее, в журнале появится следующая запись:

Re-initializing SystemForegroundService after a request to shut-down

Исправление этой ошибки было добавлено в WorkManager версии 2.10.5.

Если в вашем приложении возникает эта ошибка, обновите WorkManager до последней версии и сообщите о проблемах в системе отслеживания ошибок.

ForegroundServiceStartNotAllowedException

Ошибка.

Система выдает ошибку ForegroundServiceStartNotAllowedException.

Причина

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

Начиная с Android 12 (уровень API 31) приложениям запрещено запускать активные службы, когда приложение работает в фоновом режиме, за некоторыми исключениями. Если вы попытаетесь запустить активную службу из фонового режима и не выполните требования одного из исключений, система выдаст ошибку ForegroundServiceStartNotAllowedException. Это также произойдет, если вы не соответствуете требованиям для исключения.

Например, в приложении может быть кнопка, при нажатии на которую выполняется обработка данных, а затем запускается активная служба. В этом случае есть опасность, что пользователь нажмет кнопку и сразу же переведет приложение в фоновый режим. Затем приложение попытается запустить сервис из фонового режима. Если приложение не соответствует ни одному из указанных исключений, система выдает ошибку ForegroundServiceStartNotAllowedException.

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

В новых версиях Android некоторые исключения могут быть ограничены. Если вы изменили целевую версию Android для своего приложения, ознакомьтесь с документацией об изменениях в активных службах и убедитесь, что ваше приложение по-прежнему соответствует одному из разрешенных исключений.

Решение

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

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

SecurityException

Ошибка.

Система выдает ошибку SecurityException.

Причина

Ваше приложение попыталось запустить активную службу без необходимых разрешений.

  • Если приложение предназначено для Android 9 (уровень API 28) или более поздней версии, для запуска активной службы у него должно быть разрешение FOREGROUND_SERVICE.
  • Если приложение предназначено для Android 14 (уровень API 34) или более поздней версии, оно должно соответствовать всем требованиям для своего типа активной службы. Эти требования подробно описаны в документации по типам активных служб. В частности, обратите внимание на следующие требования:
    • Для некоторых типов активных служб требуются определенные динамические разрешения. Например, активная служба для удаленного обмена сообщениями должна иметь разрешение FOREGROUND_SERVICE_REMOTE_MESSAGING.
  • В некоторых случаях действуют дополнительные ограничения на разрешения, необходимые для определенных типов активных служб. Эти разрешения предоставляются приложению, только когда оно активно (за некоторыми исключениями). Это означает, что даже если ваше приложение запросило и получило одно из этих разрешений, при попытке запустить активную службу в фоновом режиме система выдаст ошибку SecurityException, даже если у приложения есть исключение для запуска активной службы в фоновом режиме. Подробнее об ограничениях на запуск активных служб, которым требуются разрешения на доступ во время использования…
    • Если вы запросили необходимые разрешения, но запустили активную службу до того, как убедились, что они предоставлены, может возникнуть ошибка SecurityException.

Решение

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