Случай использования:
Когда срабатывает геозона, нам нужно связаться с сервером как можно скорее. Мы решили эту проблему с помощью неявного BroadcastReceiver, вызывающего службу в течение нескольких лет, но проблематичного в новых версиях из-за фоновых ограничений Doze и Oreo.
Попытки исправления:
Мы переместили регистрацию геозоны с неявного на явный широковещательный приемник, чтобы обойти ограничение «фонового режима».
Мы попытались сделать это, как в примерах Google, т. е. широковещательный приемник вызывает enqueueWork() для JobIntentService. Проблема в том, что мы часто замечали большую «задержку» между тем, когда задание было запланировано, и тем, когда оно фактически выполнялось. Наш рекорд больше часа!
Поэтому вместо этого мы попытались перенести все функции в BroadcastReceiver и использовать goAsync() для выполнения сетевого вызова. (если вы попытаетесь выполнить сетевую операцию синхронно, вы получите исключение «нет сети из основного потока»).
Это работает, поскольку мы можем запустить поток, и он выполняет код, но сетевая операция доставляет нам проблемы.
Проблема:
Таким образом, наше текущее решение из-за вышеуказанных проблем — это явный BroadcastReceiver, использующий goAsync() для вызова сервера.
Однако сетевой вызов работает с перебоями. Мы довольно часто получаем ошибки "java.net.SocketException: Socket isclosed". Это не проблема сервера, и она всегда работает при вызове из нашего "обычного" кода приложения.
Я не уверен, почему это происходит, но я подозреваю режим Doze? Хотя я не уверен, как я могу получить это, когда приемник фактически вызывается триггером геозоны.
Вопросы:
Кто-нибудь знает, почему сетевая операция не удалась из нашего goAsync()? Опять же, многопоточность работает, просто мы получаем ошибки сокета при фактической сетевой операции.
Есть ли в более новых версиях Android какой-либо способ от триггера геозоны сделать сетевой вызов напрямую, как мы пытаемся сделать, помимо того, что мы уже пробовали?
Указатели и мысли очень ценятся!