Статьи

Основы Android: планирование повторяющихся задач

Многие приложения нуждаются в регулярных фоновых действиях. Например, в приложении «TutList», которое мы строили на основе недавней серии учебных пособий, список содержимого устарел, пока пользователь не инициирует обновление из меню параметров. Почему приложение не может просто обновлять свои данные через регулярные промежутки времени? Ну, это может и должно. Давайте реализуем эту новую функцию прямо сейчас!

В нашем последнем руководстве « Основы Android: загрузка данных с помощью служб» вы узнали, как загружать данные из потока пользовательского интерфейса независимо от какой-либо конкретной деятельности. Это эффективный способ загрузки данных, позволяющий избежать повторных загрузок и перезагрузок. Теперь вы научитесь загружать контент, даже не спрашивая пользователя.

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

Android SDK имеет систему сигнализации для приложений для использования. Механизм тревоги позволяет событиям, в частности, намерениям вещания, запускаться в определенное время или интервал. Тревоги могут быть однократными или периодическими. Периодические сигналы тревоги могут быть запланированы на очень конкретное время или настроены так, чтобы система могла запускать их в приблизительное время, что удобно для других системных событий. Сигналы тревоги могут либо разбудить устройство, либо нет. И, наконец, аварийные сигналы могут быть запланированы на основе времени с момента последней загрузки устройства (хорошо для кратковременных аварийных сигналов) или на основе времени настенных часов.

Мы знаем, что уроки Mobiletuts + публикуются ежедневно около 11:30 по Гринвичу. Таким образом, мы можем легко запланировать событие тревоги для нашего приложения, которое будет срабатывать ежедневно в 11:45 по Гринвичу, чтобы забрать новый контент. Тем не менее, мы не хотим, чтобы каждое устройство начинало загрузку с сервера Mobiletuts + одновременно, поэтому мы также будем использовать приблизительный повторяющийся тип, называемый неточным повторением.

Представьте, что у вас есть популярное приложение с миллионами пользователей. Теперь представьте, запрашивает ли это приложение данные с одного и того же сервера в одно и то же время. Фактически, с таким количеством пользователей вы, вероятно, захотите распространить обновления на несколько часов или более. Такое поведение вы увидите во многих крупных системах. Одним из способов справиться с этим было бы иметь базовое время запуска, например 11:45 по Гринвичу, а затем добавить к нему случайное количество минут или часов, чтобы распространить «массовую загрузку» на многие устройства.

Чтобы прослушивать и реагировать на намерения вещания, которые инициируются аварийными сигналами, необходимо создать приемник вещания и зарегистрировать его в системе. Для этого создайте в вашем приложении новый класс с именем AlarmReceiver и сделайте так, чтобы он расширял BroadcastReceiver. Мы поместили это в новый пакет, названный com.mamlambo.tutorial.tutlist.receiver, для организационных целей. У получателя вещания будет только одна задача: запустить службу для загрузки XML-канала. Вы уже знаете, как это сделать, из <a href = » последнего урока этой серии, так что вот приемник вещания в полном объеме:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public class AlarmReceiver extends BroadcastReceiver {
 
    private static final String DEBUG_TAG = «AlarmReceiver»;
 
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(DEBUG_TAG, «Recurring alarm; requesting download service.»);
        // start the download
        Intent downloader = new Intent(context, TutListDownloaderService.class);
        downloader.setData(Uri
                .parse(«http://feeds.feedburner.com/MobileTuts?format=xml»));
        context.startService(downloader);
    }
 
}

Приемники вещания обычно регистрируются в файле манифеста Android. Таким образом, они активны без запуска какого-либо кода, который вызвал бы метод registerReceiver () класса Context. Получатели широковещания регистрируются с помощью тега <receiver>, размещенного внутри тега приложения, например:

1
2
<receiver
    android:name=».receiver.AlarmReceiver»></receiver>

Часто приемники вещания, предназначенные для использования другими приложениями, также будут использовать фильтр намерений. Но так как мы будем ссылаться на этот широковещательный приемник по имени класса и не будем нуждаться в других приложениях для его использования, регистрация проста — только получатель.

Сигналы тревоги Android устанавливаются с помощью сервиса AlarmManager. Это системный сервис, поэтому его нельзя просто создать как обычный класс Java. Вместо этого вы должны использовать вызов метода getSystemService () для извлечения экземпляра AlarmManager и создания правильно настроенного намерения для использования с широковещательной рассылкой (тип намерения, с которым работает AlarmManager). Наконец, вы должны определить время в миллисекундах до 1145 по Гринвичу, чтобы правильно подать сигнал тревоги. Вот единственный метод setRecurringAlarm (), который инкапсулирует эти функции. Этот метод находится в классе TutListFragment:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
private void setRecurringAlarm(Context context) {
 
    // we know mobiletuts updates at right around 1130 GMT.
    // let’s grab new stuff at around 11:45 GMT, inexactly
    Calendar updateTime = Calendar.getInstance();
    updateTime.setTimeZone(TimeZone.getTimeZone(«GMT»));
    updateTime.set(Calendar.HOUR_OF_DAY, 11);
    updateTime.set(Calendar.MINUTE, 45);
     
    Intent downloader = new Intent(context, AlarmReceiver.class);
    PendingIntent recurringDownload = PendingIntent.getBroadcast(context,
            0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getActivity().getSystemService(
            Context.ALARM_SERVICE);
    alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP,
            updateTime.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, recurringDownload);
}

Объект PendingIntent, который вы видите здесь, — это просто способ обернуть намерение в объект, который позже может отправить инкапсулированное намерение извне текущего приложения.

Метод setRecurringAlarm () должен вызываться из разумного места. Мы изменили приложение для вызова этого метода при первом обновлении списка учебников:

01
02
03
04
05
06
07
08
09
10
11
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == refreshMenuId) {
        getActivity().startService(item.getIntent());
 
        // also set alarm
        Context context = getActivity().getApplicationContext();
        setRecurringAlarm(context);
    }
    return true;
}

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

Отмена тревоги осуществляется с помощью метода cancel () в AlarmManager. Он принимает один параметр, PendingIntent. Вам не нужно держать экземпляр PendingIntent рядом. Вместо этого просто создайте новый с теми же параметрами. Цель будет согласована с системой, и любой ранее установленный сигнал тревоги с теми же параметрами намерения будет отменен.

Проверка 24-часовых повторяющихся сигналов тревоги — упражнение на терпение. Вместо этого, тестирование сигналов тревоги может быть лучше всего выполнено с использованием короткого интервала. Аварийные сигналы не должны устанавливаться с очень короткими интервалами, иначе система Android имеет тенденцию ограничивать их и делать ваши тесты недействительными. Поэтому мы рекомендуем либо использовать 15-минутный интервал (INTERVAL_FIFTEEN_MINUTES), либо использовать неповторяющееся время с помощью метода set () и установить время в прошлом. Таким образом, сигнал тревоги сработает немедленно.

Вы узнали, как планировать одиночные и повторяющиеся тревоги в этом быстром уроке. Чтобы поддержать эту функцию, вы также изучили некоторые основы одного из трех основных типов намерений в Android: намерение вещания. При совместном использовании простое приложение «TutList» теперь загружает свежий учебный контент один раз в день, через несколько минут после обычного времени публикации с веб-сайта MobileTuts +.

Разработчики мобильных приложений Лорен Дарси и Шейн Кондер являются соавторами нескольких книг по разработке Android: углубленная книга по программированию под названием « Разработка беспроводных приложений для Android» и « Самс научи себя разрабатывать приложения для Android за 24 часа» . Когда они не пишут, они тратят свое время на разработку мобильного программного обеспечения в своей компании и оказание консультационных услуг. С ними можно связаться по электронной почте [email protected] , через их блог на androidbook.blogspot.com и в Twitter @androidwireless .

Купить Android-разработку беспроводных приложений, 2-е издание Купить Sam's Teach Yourself для Android-разработки приложений в течение 24 часов Код Мамламбо в Код-Каньоне