Статьи

Использование API JobScheduler на Android Lollipop

В этом руководстве вы узнаете, как использовать 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 .

Для начала вам понадобится создать новый проект 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» />

С 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 чтобы установить требования, когда ваша служба должна работать. Используя их, вы сможете улучшить работу собственных приложений, помня о потреблении энергии.