Фоновые процессы могут потреблять много памяти и заряда батареи. Например, неявная широковещательная рассылка может запустить множество фоновых процессов, которые зарегистрированы для ее прослушивания, даже если эти процессы не выполняют много работы. Это может существенно повлиять на производительность устройства и удобство использования.
Чтобы избежать системных ограничений, используйте подходящий API для фоновой задачи. В обзоре фоновых задач рассказывается, как выбрать подходящий API.
Ограничения, установленные пользователем
Если приложение демонстрирует некоторые из существенных неполадок, описанных в Android Vitals, система предлагает пользователю ограничить доступ этого приложения к системным ресурсам.
Если система обнаружит, что приложение потребляет слишком много ресурсов, она уведомит об этом пользователя и предложит ему ограничить действия приложения. Вот некоторые примеры:
- Слишком долгая работа запретов блокировки. Один частичный запрет блокировки действует в течение часа, когда экран выключен.
- Избыточное количество фоновых служб. Если целевой уровень API приложения ниже 26 и в нем слишком много фоновых служб.
Точные ограничения определяются производителем устройства. Например, в сборках AOSP приложения с ограниченным доступом не могут выполнять задания, запускать будильники или использовать сеть, за исключением случаев, когда приложение находится на переднем плане.
Ограничения на получение широковещательных сообщений о сетевой активности
Приложения не получают широковещательные сообщения CONNECTIVITY_ACTION, если они зарегистрированы для их получения в манифесте. Процессы, зависящие от этих сообщений, не запускаются. Это может вызвать проблемы в приложениях, которые прослушивают изменения в сети или выполняют массовую сетевую активность при подключении устройства к сети без тарификации трафика. В Android есть несколько способов обойти это ограничение. Выбор зависит от того, что должно делать ваше приложение.
Запланировать работу в сетях без тарификации трафика
При создании WorkRequest добавьте NetworkType.UNMETERED Constraint.
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, private val 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 планирования задач.