Проблемы с запуском фоновых задач на Android-устройствах

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

Фоновое сканирование BLE для устройств Android можно разделить на две разные группы в зависимости от механизмов, используемых для планирования фоновых задач. За последние несколько лет Android изменил фоновую обработку и добавил режим Doze, ограниченные неявные трансляции и ограниченное фоновое поведение и. Большинство новых решений не будут работать для старых версий Android, и все старые решения будут убиты Android в новых версиях. Итак, в этой статье мы рассмотрим две разные стратегии сканирования в фоновом режиме - для версий до API 26 (Oreo) и после.

Фоновые задачи на устройствах Android с уровнем API менее 26 (Oreo)

Для всех старых версий Android до Android Oreo существует рабочий метод сканирования в фоновом режиме с использованием диспетчера аварийных сигналов и службы с приемником вещания. Радиоприемник получит сигнал будильника и запустит службу, при которой Navigine SDK будет инициализирован и запущен на 10 секунд. По истечении этого времени SDK будет завершен, а сервис будет убит. Этот будильник можно установить с интервалом не менее одной минуты, и он будет работать без каких-либо ограничений на старых устройствах.

Внутри класса обслуживания вы можете объявить намерение обработки от широковещательного приемника и запустить Navigine SDK или другие манипуляции, которые вы хотите выполнить. Это решение не будет работать на устройствах Android с версией, начиная с 26, потому что Android не позволит запустить службу, когда ваше приложение будет убито, поэтому здесь нам нужны лучшие решения.

Фоновые задачи, начиная с Android Oreo

Начиная с API 26, Android начал блокировать службы, работающие при отключении устройства, и предоставил несколько решений для выполнения ваших задач в фоновом режиме. Но основная трудность заключается в том, что эти решения также не будут работать в режиме дремоты (если пользователь оставляет устройство отключенным от сети и неподвижным в течение определенного периода времени с выключенным экраном, устройство переходит в режим дремоты). Вот список ограничений, когда приложение перешло в режим Doze:

Далее мы расскажем о каждом найденном нами решении и приведем примеры кода. Каждый из них можно использовать, если вы решите не сражаться в режиме Doze. Поскольку нам нужно сканировать устройства BLE каждые несколько минут, нам необходимо запускать периодические фоновые задачи. Кроме того, мы предоставим еще два решения, которые будут игнорировать режим Doze, но потребуют больше ресурсов или будут иметь дополнительные уведомления.

Periodic J ob Scheduler.
Планировщик заданий может использоваться, начиная с уровня API Android 23 и заменяет Service + Alarm Manager для выполнения фоновых задач. Планировщик периодических заданий можно активировать не реже, чем каждые 15 минут, и у него есть много возможностей, если вам нужны некоторые условия для вашего планировщика заданий, например, необходимость запуска только в том случае, если устройство подключено к Интернету, должно заряжаться и т. Д. Для использования этого метода вам следует расширить класс JobService и переопределить метод onStartJob для запуска вашей задачи. И запустите планировщик заданий, чтобы выполнять периодическое задание. Не забудьте добавить свою службу в файл манифеста. Вот пример кода, как запустить планировщик периодических заданий:

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

Аварийный сигнал с. setAndAllowWhileIdle () и JobScheduler.
Общие диспетчеры аварийных сигналов с .set () или .setRepeating () будет хорошо работать, только когда устройство не находится в режиме ожидания, потому что Android проигнорирует их и перенесет на следующий раз. Использование. setAndAllowWhileIdle () позволит вызвать сигнал тревоги, но даже в этом случае планировщик заданий будет проигнорирован.
Однако вы можете добавить . setOverrideDeadline (время в миллисекундах) в планировщик заданий, и он запустит это запланированное задание, когда устройство выйдет из режима дремоты. Вот пример кода для метода onReceive нашего расширения BroadcastReceiver:

В нашем случае мы решили уничтожить эти задания, если прошло более 30 минут после того, как они были запланированы. Это решение также не решит проблему с запуском фоновых задач в режиме ожидания, но задания не будут пропускаться, как в планировщике периодических заданий. Имейте в виду, что даже в режиме Doze эти сигналы тревоги будут проигнорированы, если вы попытаетесь вызвать их чаще, чем раз в 9 минут.

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

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

Как вы можете видеть на этом снимке экрана, пользователь всегда будет видеть это уведомление, которое нельзя отменить. Использование службы переднего плана увеличит вероятность того, что ваше приложение будет удалено быстрее, чем могло бы быть. Также стоит отметить, что ваше приложение будет использовать больше энергии и ресурсов устройства.
Вот пример кода службы переднего плана:

Использование push-уведомлений.
Другой способ запускать фоновые задачи даже в режиме Doze для отправки уведомлений вашему приложению с сервера. Эти уведомления заставят ваше приложение выйти из режима Doze, и ваша работа будет выполнена. Но в этом случае вам нужно будет потратить больше ресурсов на запуск и обслуживание вашего сервиса. Вы можете найти дополнительную информацию об использовании Firebase Cloud Messaging для запуска фоновых служб по этой ссылке.

Заключение

Со временем Google усиливает способность запускать фоновые задачи, поэтому разработчикам необходимо придумывать новые решения и уловки, например отправлять push-уведомления для пробуждения устройства из режима Doze. В защиту Android можно сказать, что они используют свои действия для защиты пользователей от нежелательных и ненужных действий в фоновом режиме, которые будут использовать ресурсы телефона и выполнять нежелательные, а иногда и вредоносные задачи. Кстати, вышеперечисленные решения помогут вам работать с соблюдением требований Android или обходить режим Doze.

Автор - разработчик Android Navigine - Иль Кадыров