В этом руководстве вы узнаете, как использовать API JobScheduler
доступный в Android Lollipop. API-интерфейс JobScheduler
позволяет разработчикам создавать задания, которые выполняются в фоновом режиме при соблюдении определенных условий.
Вступление
При работе с Android возможны случаи, когда вы захотите запустить задачу позднее или при определенных условиях, например, когда устройство подключено к источнику питания или подключено к сети Wi-Fi. К счастью, благодаря API 21, известному большинству людей как Android Lollipop, Google предоставил новый компонент, известный как API JobScheduler
для обработки этого самого сценария.
API-интерфейс JobScheduler
выполняет операцию для вашего приложения, когда выполняется набор предопределенных условий. В отличие от класса AlarmManager
, время не точное. Кроме того, API-интерфейс JobScheduler
способен JobScheduler
различные задания для совместной работы. Это позволяет вашему приложению выполнять данную задачу, уделяя внимание аккумулятору устройства за счет контроля времени.
В этой статье вы узнаете больше об API-интерфейсе JobService
классе JobService
, используя их для запуска простой фоновой задачи в приложении Android. Код для этого урока доступен на GitHub .
1. Создание службы работы
Для начала вам понадобится создать новый проект Android с минимально необходимым API 21, потому что API JobScheduler
был добавлен в самую последнюю версию Android и на момент написания не был обратно совместим через поддержка библиотеки.
Предполагая, что вы используете Android Studio, после того, как вы нажмете кнопку «Готово» для нового проекта, у вас должно быть приложение «Hello World». Первый шаг, который вы собираетесь сделать с этим проектом, — это создать новый класс Java. Для простоты давайте назовем его JobSchedulerService и расширим класс JobService
, который требует создания двух методов onStartJob(JobParameters params)
и onStopJob(JobParameters params)
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public class JobSchedulerService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
|
onStartJob(JobParameters params)
— это метод, который необходимо использовать, когда вы начинаете свою задачу, потому что это то, что система использует для запуска уже запланированных заданий. Как видите, метод возвращает логическое значение. Если возвращаемое значение равно false
, система предполагает, что выполнение любой задачи не заняло много времени и выполняется ко времени возврата метода. Если возвращаемое значение равно true
, то система предполагает, что задача займет некоторое время, и jobFinished(JobParameters params, boolean needsRescheduled)
за выполнение этой задачи ложится на вас, разработчика, с помощью вызова jobFinished(JobParameters params, boolean needsRescheduled)
,
onStopJob(JobParameters params)
используется системой для отмены отложенных задач при получении запроса на отмену. Важно отметить, что если onStartJob(JobParameters params)
возвращает значение false
, система предполагает, что в данный момент нет заданий, выполняющихся при получении запроса на отмену. Другими словами, он просто не будет вызывать onStopJob(JobParameters params)
.
Следует отметить, что служба заданий работает в главном потоке вашего приложения. Это означает, что вам нужно использовать другой поток, обработчик или асинхронную задачу, чтобы запускать более длинные задачи, чтобы не блокировать основной поток. Поскольку методы многопоточности выходят за рамки этого учебного пособия, давайте JobSchedulerService
его простым и реализуем обработчик для запуска нашей задачи в классе JobSchedulerService
.
01
02
03
04
05
06
07
08
09
10
11
12
|
private Handler mJobHandler = new Handler( new Handler.Callback() {
@Override
public boolean handleMessage( Message msg ) {
Toast.makeText( getApplicationContext(),
«JobService task running», Toast.LENGTH_SHORT )
.show();
jobFinished( (JobParameters) msg.obj, false );
return true;
}
} );
|
В обработчике вы реализуете метод handleMessage(Message msg)
который является частью экземпляра Handler
и запускаете логику вашей задачи. В этом случае мы делаем все очень просто и Toast
сообщение Toast
из приложения, хотя именно здесь вы бы поместили свою логику для таких вещей, как синхронизация данных.
Когда задача выполнена, вам нужно вызвать jobFinished(JobParameters params, boolean needsRescheduled)
чтобы система знала, что вы выполнили эту задачу и что она может начать ставить в очередь следующую операцию. Если вы этого не сделаете, ваши задания будут выполняться только один раз, и вашему приложению не будет разрешено выполнять дополнительные задания.
Два параметра, которые jobFinished(JobParameters params, boolean needsRescheduled)
— это JobParameters
которые были переданы в класс JobService
в onStartJob(JobParameters params)
и логическое значение, которое позволяет системе узнать, следует ли перепланировать задание на основе исходного требования к работе. Это логическое значение полезно понять, потому что именно так вы обрабатываете ситуации, когда ваша задача не может быть выполнена из-за других проблем, таких как сбой сетевого вызова.
Handler
экземпляр Handler
, вы можете приступить к реализации onStartJob(JobParameters params)
и onStopJob(JobParameters params)
для управления своими задачами. Вы заметите, что в следующем фрагменте кода метод onStartJob(JobParameters params)
возвращает true
. Это связано с тем, что вы собираетесь использовать экземпляр Handler
для управления своей операцией, а это значит, что выполнение может занять больше времени, чем метод onStartJob(JobParameters params)
. Возвращая значение true
, вы jobFinished(JobParameters params, boolean needsRescheduled)
приложению, что вы будете вызывать метод jobFinished(JobParameters params, boolean needsRescheduled)
вручную jobFinished(JobParameters params, boolean needsRescheduled)
. Вы также заметите, что число 1
передается экземпляру Handler
. Это идентификатор, который вы собираетесь использовать для ссылки на задание.
01
02
03
04
05
06
07
08
09
10
11
|
@Override
public boolean onStartJob(JobParameters params) {
mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) );
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
mJobHandler.removeMessages( 1 );
return false;
}
|
Как только вы закончите с Java-частью JobSchedulerService
класс, вам нужно зайти в AndroidManifest.xml и добавить узел для службы, чтобы ваше приложение имело право связывать и использовать этот класс в качестве JobService
.
1
2
|
<service android:name=».JobSchedulerService»
android:permission=»android.permission.BIND_JOB_SERVICE» />
|
2. Создание планировщика заданий
С JobSchedulerService
Класс закончен, мы можем начать смотреть на то, как ваше приложение будет взаимодействовать с API JobScheduler
. Первое, что вам нужно будет сделать, это создать объект JobScheduler
, который называется mJobScheduler
в примере кода, и инициализировать его, получив экземпляр системной службы JOB_SCHEDULER_SERVICE
. В примере приложения это делается в MainActivity
учебный класс.
1
2
|
mJobScheduler = (JobScheduler)
getSystemService( Context.JOB_SCHEDULER_SERVICE );
|
Если вы хотите создать запланированное задание, вы можете использовать JobInfo.Builder
для JobInfo
объекта JobInfo
который передается вашему сервису. Чтобы создать объект JobInfo.Builder
, JobInfo.Builder
принимает два параметра. Первый — это идентификатор задания, которое вы будете запускать, а второй — имя компонента службы, которую вы будете использовать с API-интерфейсом JobScheduler
.
1
2
3
|
JobInfo.Builder builder = new JobInfo.Builder( 1,
new ComponentName( getPackageName(),
JobSchedulerService.class.getName() ) );
|
Этот конструктор позволяет вам установить множество различных параметров для контроля, когда ваша работа будет выполняться. В следующем фрагменте кода показано, как можно настроить выполнение задачи каждые три секунды.
1
|
builder.setPeriodic( 3000 );
|
Другие методы включают в себя:
-
setMinimumLatency(long minLatencyMillis)
: это заставляет вашу работу не запускаться до тех пор, пока не пройдет указанное количество миллисекунд. Это несовместимо сsetPeriodic(long time)
и вызовет исключение, если они оба используются. -
setOverrideDeadline(long maxExecutionDelayMillis)
: это установит крайний срок для вашей работы. Даже если другие требования не будут выполнены, ваша задача начнется примерно через указанное время. Как иsetMinimumLatency(long time)
, эта функция является взаимоисключающей сsetPeriodic(long time)
и будет вызывать исключение, если они оба используются. -
setPersisted(boolean isPersisted)
: эта функция сообщает системе, должна ли ваша задача продолжать существовать после перезагрузки устройства. -
setRequiredNetworkType(int networkType)
: эта функция сообщит вашей работе, что ее можно запустить, только если устройство находится в сети определенного типа. Значением по умолчанию являетсяJobInfo.NETWORK_TYPE_NONE
, что означает, что задача может выполняться независимо от наличия сетевого подключения. Двумя другими доступными типами являютсяJobInfo.NETWORK_TYPE_ANY
, для которых требуетсяJobInfo.NETWORK_TYPE_ANY
определенного типа сетевого подключения, иJobInfo.NETWORK_TYPE_UNMETERED
, который требует, чтобы устройствоJobInfo.NETWORK_TYPE_UNMETERED
сети, отличной от сотовой. -
setRequiresCharging(boolean requiresCharging)
: использование этой функции сообщит вашему приложению, что задание не должно начинаться, пока устройство не начнет заряжаться. -
setRequiresDeviceIdle(boolean requiresDeviceIdle)
: Это говорит о том, что ваша работа не должна запускаться, если пользователь не использует свое устройство и не использует его в течение некоторого времени.
Важно отметить, что setRequiredNetworkType(int networkType)
, setRequiresCharging(boolean requireCharging)
и setRequiresDeviceIdle(boolean requireIdle)
могут привести к тому, что ваша работа никогда не запустится, если только setOverrideDeadline(long time)
также не установлен, позволяя вашей работе выполняться, даже если условия не выполняются , После определения предпочтительных условий вы можете создать объект JobInfo
и отправить его в ваш объект JobScheduler
как показано ниже.
1
2
3
|
if( mJobScheduler.schedule( builder.build() ) <= 0 ) {
//If something goes wrong
}
|
Вы заметите, что операция по schedule
возвращает целое число. Если schedule
не выполнено, возвращается нулевое или меньшее значение, соответствующее коду ошибки. В противном случае он вернет идентификатор задания, который мы определили в JobInfo.Builder
.
Если ваше приложение требует остановки определенных или всех заданий, вы можете сделать это, вызвав cancel(int jobId)
или cancelAll()
JobScheduler
объекта JobScheduler
.
1
|
mJobScheduler.cancelAll();
|
Теперь вы сможете использовать API-интерфейс JobScheduler
со своими приложениями для пакетных заданий и выполнения фоновых операций.
Вывод
В этой статье вы узнали, как реализовать подкласс JobService
который использует объект Handler
для запуска фоновых задач для вашего приложения. Вы также узнали, как использовать JobInfo.Builder
чтобы установить требования, когда ваша служба должна работать. Используя их, вы сможете улучшить работу собственных приложений, помня о потреблении энергии.