Для планирования заданий я использую следующий довольно простой код:
Код: Выделить всё
PersistableBundle extras = new PersistableBundle();
extras.putInt("anExtraInt", someInt);
int networkConstraint = useUnmetered ? JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;
ComponentName componentName = new ComponentName(context, MyJobService.class);
JobInfo jobInfo = new JobInfo.Builder(jobId, componentName)
.setRequiredNetworkType(networkConstraint)
.setExtras(extras)
.build();
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);
короткая версия вопроса
Как указать максимальную задержку для всех соблюдаемых ограничений и фактического выполнения задания, например. "запустить задание в течение 2 секунд после подключения к сети"?
Большая версия (с бессвязностью)
Проблема
Я обнаружил, что на некоторых устройствах, если задание запланировано на период, когда сетевое ограничение уже удовлетворено, задание запустится немедленно (или достаточно быстро, чтобы это было воспринято пользователем).
Но на других устройствах, даже если подходящее сетевое соединение уже доступно (чтобы задание могло быть запущено немедленно ), перед его фактическим запуском происходит значительная задержка. Поэтому, если это реакция на действие пользователя, создается впечатление, что ничего не произошло и приложение не работает.
Я прекрасно понимаю, что, вероятно, именно это и было намерением JobScheduler... что система должна запланировать задание так, чтобы оно наилучшим образом соответствовало другим требованиям, и что нет никакой гарантии, что задание будет запущено немедленно, когда все ограничения будут выполнены.
Но было бы неплохо иметь возможность некоторого контроля над этим, где это необходимо. Поэтому для заданий, которые выполняются по расписанию, без участия пользователя, предоставить системе полный контроль над точным временем — это нормально.
Но если задание выполняется в ответ на действие пользователя, я хочу, чтобы задание выполнялось без задержек... при условии, что сетевое соединение есть. (Если соединения нет, может отображаться сообщение о том, что действие произойдет при восстановлении сетевого подключения, а затем JobScheduler позаботится о том, чтобы задание было выполнено после восстановления сети.)
setOverrideDeadline() не является решением?
Я вижу, что JobInfo.Builder имеет setOverrideDeadline() , и это почти то, что мне нужно. Но это определяет максимальную задержку с момента планирования задания (т. е. запуск задания через 10 секунд, даже если все ограничения не соблюдены), а не с момента, когда все ограничения были удовлетворены. (т. е. запустить задание в течение 10 секунд после удовлетворения всех ограничений).
EDIT: кажется, существует досадная ошибка, которая может привести к тому, что задание будет запускаться дважды при использовании setOverrideDeadline(): см. здесь и здесь.
А как насчет Firebase JobDispatcher?
Я вижу это Firebase JobDispatcher имеет триггер Trigger.NOW («означает, что задание должно быть запущено, как только его ограничения времени выполнения будут удовлетворены»). Возможно, это правильный путь, если JobScheduler не поддерживает это изначально? Меня оттолкнул Firebase JobDispatcher, потому что кажется, что он использует кувалду, чтобы расколоть орех... и похоже, что Firebase занимается обменом облачными сообщениями и т. д., что очень далеко от локального планирования задач (которое должно быть полностью местный интерес). И, похоже, для этого требуются сервисы Google Play, что опять-таки кажется совершенно ненужным для локального планирования задач. Более того, если с помощью Firebase возможен немедленный запуск, а Firebase просто использует JobScheduler для Android L+, то наверняка можно сделать это напрямую с помощью JobScheduler, не полагаясь на Firebase?
РЕДАКТИРОВАТЬ: Я попробовал это, и даже Trigger.NOW не гарантирует немедленный ответ... на самом деле, я обнаружил, что задержка составляет почти ровно 30 секунд при мое устройство, что странно.
В противном случае...
В настоящее время я могу видеть только так чтобы гарантировать немедленное выполнение (если ограничения соблюдены), нужно не использовать JobScheduler.
Или, возможно, выполните начальную проверку ограничений вручную и запустите задание с setOverrideDeadline(), равным 0, если все ограничения соблюдены, в противном случае запустите его без setOverrideDeadline().
Казалось бы гораздо предпочтительнее просто иметь возможность контролировать время самого JobScheduler, примерно так же, как вы можете это сделать с помощью метода setWindow() AlarmManager.
Подробнее здесь: https://stackoverflow.com/questions/393 ... -being-run
Мобильная версия