Фоновые процессы могут потреблять много памяти и заряда батареи. Например, неявная широковещательная рассылка может запустить множество фоновых процессов, зарегистрировавшихся для ее прослушивания, даже если эти процессы не выполняют большой работы. Это может существенно повлиять как на производительность устройства, так и на удобство использования для пользователя.
Чтобы избежать системных ограничений, убедитесь, что вы используете правильный API для вашей фоновой задачи. Документация по обзору фоновых задач поможет вам выбрать подходящий API для ваших нужд.
Ограничения, инициированные пользователем
Если приложение демонстрирует некоторые из проблемных функций, описанных в разделе «Жизненно важные параметры Android» , система предлагает пользователю ограничить доступ этого приложения к системным ресурсам.
Если система обнаруживает, что приложение потребляет чрезмерное количество ресурсов, она уведомляет пользователя и предоставляет ему возможность ограничить действия приложения. К действиям, которые могут вызвать уведомление, относятся:
- Чрезмерное количество блокировок пробуждения : 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 планирования задач .