Фоновые процессы могут занимать много памяти и батареи. Например, неявная широковещательная рассылка может запустить множество фоновых процессов, зарегистрированных для ее прослушивания, даже если эти процессы могут не выполнять большой работы. Это может оказать существенное влияние как на производительность устройства, так и на удобство использования.
Чтобы избежать системных ограничений, убедитесь, что вы используете правильный API для своей фоновой задачи. Документация по обзору фоновых задач поможет вам выбрать API, соответствующий вашим потребностям.
Ограничения, инициируемые пользователем
Если приложение демонстрирует некорректное поведение, описанное в Android Vitals , система предлагает пользователю ограничить доступ этого приложения к системным ресурсам.
Если система замечает, что приложение потребляет слишком много ресурсов, она уведомляет пользователя и дает ему возможность ограничить действия приложения. Поведения, которые могут вызвать уведомление, включают в себя:
- Чрезмерные блокировки пробуждения : 1 частичная блокировка пробуждения удерживается в течение часа, когда экран выключен.
- Чрезмерное количество фоновых служб : если приложение нацелено на уровни API ниже 26 и имеет слишком много фоновых служб.
Точные налагаемые ограничения определяются производителем устройства. Например, в сборках AOSP приложения с ограниченным доступом не могут запускать задания, активировать сигналы тревоги или использовать сеть, за исключением случаев, когда приложение находится на переднем плане.
Ограничения на получение трансляций сетевой активности
Приложения не получают широковещательные сообщения CONNECTIVITY_ACTION
, если они регистрируются для их получения в своем манифесте, и процессы, зависящие от этого широковещательного сообщения, не запускаются. Это может создать проблему для приложений, которые хотят прослушивать изменения в сети или выполнять массовые сетевые действия, когда устройство подключается к сети без ограничений. В платформе Android уже существует несколько решений, позволяющих обойти это ограничение, но выбор правильного зависит от того, чего вы хотите от своего приложения.
Запланируйте работу на безлимитных подключениях
При создании WorkRequest
добавьте Constraint
NetworkType.UNMETERED
.
fun scheduleWork(context: Context) {
val workManager = WorkManager.getInstance(context)
val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
)
.build()
workManager.enqueue(workRequest)
}
Когда условия для вашей работы выполняются, ваше приложение получает обратный вызов для запуска метода doWork()
в указанном классе Worker
.
Отслеживайте сетевое подключение во время работы приложения.
Запущенные приложения по-прежнему могут прослушивать CONNECTIVITY_CHANGE
с зарегистрированным BroadcastReceiver
. Однако API ConnectivityManager
предоставляет более надежный метод запроса обратного вызова только при выполнении определенных условий сети.
Объекты NetworkRequest
определяют параметры сетевого обратного вызова с точки зрения NetworkCapabilities
. Объекты NetworkRequest
создаются с помощью класса NetworkRequest.Builder
. registerNetworkCallback
затем передает объект NetworkRequest
в систему. Когда условия сети выполняются, приложение получает обратный вызов для выполнения метода onAvailable()
, определенного в его классе ConnectivityManager.NetworkCallback
.
Приложение продолжает получать обратные вызовы до тех пор, пока приложение не завершится или не вызовет unregisterNetworkCallback() .
Ограничения на прием изображений и видеотрансляций
Приложения не могут отправлять или получать трансляции ACTION_NEW_PICTURE или ACTION_NEW_VIDEO . Это ограничение помогает снизить влияние на производительность и удобство работы пользователя, когда нескольким приложениям приходится выходить из режима ожидания для обработки нового изображения или видео.
Определите, какие органы управления контентом инициировали работу
WorkerParameters
позволяет вашему приложению получать полезную информацию о том, какие органы управления контентом и URI инициировали работу:
List<Uri> getTriggeredContentUris()
Возвращает список URI, которые инициировали работу. Это пустое поле, если либо ни один URI не инициировал работу (например, работа была запущена из-за крайнего срока или по какой-либо другой причине), либо количество измененных URI больше 50.
List<String> getTriggeredContentAuthorities()
Возвращает строковый список органов управления контентом, которые инициировали работу. Если возвращенный список не пуст, используйте getTriggeredContentUris()
чтобы получить сведения о том, какие URI изменились.
Следующий пример кода переопределяет метод CoroutineWorker.doWork()
и записывает центры управления контентом и URI, которые инициировали задание:
class MyWorker(
appContext: Context,
params: WorkerParameters
): CoroutineWorker(appContext, params)
override suspend fun doWork(): Result {
StringBuilder().apply {
append("Media content has changed:\n")
params.triggeredContentAuthorities
.takeIf { it.isNotEmpty() }
?.let { authorities ->
append("Authorities: ${authorities.joinToString(", ")}\n")
append(params.triggeredContentUris.joinToString("\n"))
} ?: append("(No content)")
Log.i(TAG, toString())
}
return Result.success()
}
}
Тестирование приложения с учетом системных ограничений
Оптимизация ваших приложений для работы на устройствах с низким объемом памяти или в условиях нехватки памяти может повысить производительность и удобство использования. Удаление зависимостей от фоновых служб и неявных приемников широковещательной рассылки, зарегистрированных в манифесте, может помочь вашему приложению лучше работать на таких устройствах. Рекомендуется оптимизировать приложение для работы без использования этих фоновых процессов.
Некоторые дополнительные команды Android Debug Bridge (ADB) могут помочь вам протестировать поведение приложения с отключенными фоновыми процессами:
Чтобы смоделировать условия, когда неявные широковещательные и фоновые службы недоступны, введите следующую команду:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore
Чтобы повторно включить неявные широковещательные и фоновые службы, введите следующую команду:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
Дальнейшая оптимизация вашего приложения
Другие хорошие способы оптимизации поведения фоновых задач см. в документации по оптимизации использования батареи для API-интерфейсов планирования задач .