- Android Studio AlarmManager не работает в определенное время
- 1 ответ
- Похожие вопросы:
- AlarmManager после перезагрузки
- Alarm Service — сигнализация
- Теория
- Менеджер оповещений AlarmManager
- Методы
- Параметры
- Служба
- Установка времени для сигнализаций
- Полный список
- PendingIntent
- Флаги
- FLAG_CANCEL_CURRENT
- FLAG_UPDATE_CURRENT
- FLAG_ONE_SHOT
- FLAG_NO_CREATE
- Как оно там внутри работает
- Отмена
- requestCode
- AlarmManager
Android Studio AlarmManager не работает в определенное время
Это код для диспетчера сигнализации:
Это широковещательный класс:
Но в установленное время я не получаю никакого сообщения (я не вижу тостового сообщения со словом Hello). Кроме того, в Манифесте XML я установил внутренний тег приложения:
Класс SampleBootReceiver-это публичный класс в домашнем классе
Не могли бы вы помочь мне с этим? Заранее спасибо
1 ответ
Здравствуйте, если я создам alarmManager и установлю его на определенное время и выключу свой смартфон, после перезагрузки, возможно ли приложение сделать старый будильник? (мой смартфон был выключен) Я хочу знать, можно ли это сделать легко. Спасибо! вот как я ставлю будильник: AlarmManager am =.
Недавно я работаю над приложением, которое должно запускать службу каждый день в определенное время. Для этого я использую AlarmManager. Мой вопрос таков: после активации AlarmManager (из сервиса) могу ли я уничтожить сервис, и AlarmManager все равно позвонит мне вовремя? Если нет, то есть ли.
Вы используете setInexactRepeating , поэтому OS будет решать, когда включить вашу сигнализацию. OS пытается сгруппировать сигналы тревоги вместе, чтобы сэкономить заряд батареи.
Начиная с API 19 (Build.VERSION_CODES.KITKAT) подача сигнала тревоги неточна: OS будет переключать сигналы тревоги, чтобы свести к минимуму пробуждение и использование батареи. Существуют новые APIs для поддержки приложений, которые нуждаются в строгих гарантиях доставки; см. setWindow(int, long, long, android.app.PendingIntent) и setExact(int, long, android.app.PendingIntent). Приложения, чей targetSdkVersion является более ранним, чем API 19, будут продолжать видеть предыдущее поведение в которые все сигналы тревоги доставляются точно по запросу.
Похожие вопросы:
С помощью AlarmManager вы можете установить будильник на определенное время и повторить его через определенный промежуток времени alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP.
Я хочу посылать радиопередачу в определенное время дня. Я написал какой-то код, но календарь возвращает неправильную дату, и трансляция делает бесконечный цикл. Что я сделал не так? Boolean.
Я хочу установить будильник на android, но он не работает, вот мой код.. Я использовал ожидающее намерение, чтобы запустить будильник в определенное время, но когда я запускаю приложение на своем.
Здравствуйте, если я создам alarmManager и установлю его на определенное время и выключу свой смартфон, после перезагрузки, возможно ли приложение сделать старый будильник? (мой смартфон был.
Недавно я работаю над приложением, которое должно запускать службу каждый день в определенное время. Для этого я использую AlarmManager. Мой вопрос таков: после активации AlarmManager (из сервиса).
Я знаю, как запустить фоновую службу в android даже в определенное время. Я использовал AlarmManager для достижения этой цели, но я хочу начать эту службу ежедневно в это время. Предположим, я хочу.
В настоящее время я пытаюсь запустить фрагмент кода в определенное время. После некоторых исследований я думаю, что правильный путь — это использовать AlarmManger . Код должен выполняться каждый.
Я хочу установить обои ежедневно в определенное время,и для этого я использую AlarmManager в android для вызова функции set wallpaper. Вот мой код, где я установил будильник, чтобы сменить обои.
Я хочу запустить службу в определенное время, и для этого я использую код AlarmManager.My ниже. public static void setServiceAlarm(Context context, boolean isOn) < Intent i = new Intent(context.
У меня есть приложение с socket based push to app, чтобы открыть и показать пользователю критическую работу, такую как получение заказов в магазине. У меня есть требование бить тревогу за 10 минут.
Источник
AlarmManager после перезагрузки
Я правильно понимаю, что alarmManager сработает ровно через 24 ч?
Допустим правильно.
Утром перезагружаю устройство, BroadcastReceiver запускает AlarmManager.
Во сколько сработает теперь alarmManager, утром следующего дня?
Как запомнить время первого запуска? Чтоб срабатывал в 18-00?
Добавлено через 1 минуту
System.currentTimeMillis() видимо надо запоминать?
Добавлено через 57 секунд
А тогда он завтра вообще не сработает.
AlarmManager не работает после закрытия приложения
Всем привет, сделал ресивер + нацепил туда alarm вот код в классе ресивера public void.
Не срабатывает AlarmManager после выключения экрана
Доброго дня! Прошу помощи. Приложение выполняет отложенные задачи через AlarmManager. Все отлично.
Продолжение работы батника после перезагрузки системы или запуск после перезагрузки
Добрый день! Нужно реализовать в .bat файле следующие: @echo off start /wait *.exe/s.
После восстановления работает до перезагрузки. После перезагрузки все сначала. Переустановка ОС не помогла.
Такая проблема: после включения ноутбука потребовалось восстановление запуска и системы. После.
Медленный интернет до перезагрузки ноутбука, а после перезагрузки быстрый
Здравствуйте! Есть ноутбук MSI Windows 10, подключен дома к домашнему запароленному wi-fi. Проблема.
После установки драйверов на видеокарту, сразу после перезагрузки появляется синий экран
после переустановки Windows и установки дров на видеокарту сразу после перезагрузки появляется.
После разгона процессора через биос ,после перезагрузки появляется черный экран
Процессор Xeon e 5440.Материнская плата asrock p5gtm vs3.Блок питания на 360в.При разгоне с 2.83 до.
После установки драйвера видеокарты GeForce появляется синий экран после перезагрузки компьютера
после установки драйвера видеокарты geforce ,после перезагрузки быстро появляется синий экран не.
Источник
Alarm Service — сигнализация
2-й курс/Закрытая зона
Теория
Служба Alarm Service используется для отправки пользователю разовых или повторяющихся сообщений в заданное время. Таким образом вы сможете создавать различные планировщики, будильники, реализовать выполнение регулярных сетевых запросов, запуска трудоёмких или дорогих операций, запланированных на определенное время и другие приложения, которые должны срабатывать по расписанию.
Важно помнить, что механизм сигнализации не зависит от конкретного приложения, это значит, что прописанные намерения сработают в определённое время или с заданным интервалом. Так как сигнализация устанавливается за пределами вашего приложения, она может быть использована для вызова событий, принадлежащих приложению, или для запуска самого приложения, даже если оно закрыто. Сигнализация может стать мощным инструментом в сочетании с приёмниками широковещательных намерений.
Таким образом, сигнализация чрезвычайно полезна, когда речь идет о снижении требований к ресурсам, особенно в случае с приложениями, которые работают в фоновом режиме, позволяя останавливать сервисы и отключать таймеры, сохраняя возможность выполнять запланированные действия.
Сигнализация в Android остается активной даже тогда, когда устройство находится в режиме ожидания и при необходимости может его «пробудить», однако она отменяется каждый раз, когда устройство перезагружается.
Менеджер оповещений AlarmManager
Доступ к службе Alarm Service осуществляется при помощи объекта AlarmManager следующим образом:
Методы
- cancel() — удаляет все сигнализации
- setTime() — устанавливает системное время
- setTimeZone() — устанавливает временную зону
- set() — задаёт одноразовую сигнализацию
- setExact() — в API 19 (Kitkat) метод set() заменили на новый метод с теми же параметрами
- setRepeating() — задаёт повторяющиеся сигнализации с фиксированным временным интервалом
- setInexactRepeating() — устанавливает повторяющиеся сигнализации без строгого требования к точности периода повторения. Этот метод является предпочтительнее предыдущего для экономии ресурсов системы
Чтобы создать сигнализацию, которая сработает всего один раз, используйте метод set(), укажите тип сигнализации, время срабатывания и ожидающее намерение, которое должно запуститься. Если время срабатывания, которое вы указали для сигнализации, уже прошло, указанное намерение запустится немедленно.
Параметры
Методы set(), setRepeating(), setInexactRepeating() используют следующие параметры:
- typeOne — тип используемого времени (системное или всемирное время UTC), который определяется константами
- ELAPSED_REALTIME — запускает ожидающее намерение, основываясь на времени, которое прошло с момента загрузки устройства, но не с момента выхода из режима ожидания. Это время включает любой временной промежуток, в котором устройство находилось в данном режиме. Обратите внимание, что прошедшее время вычисляется на основании того, когда устройство было загружено. Используется системное время
- ELAPSED_REALTIME_WAKEUP — по прошествии указанного промежутка времени с момента загрузки выводит устройство из спящего режима и запускает ожидающее намерение. Используется системное время
- RTC — запускает ожидающее намерение в указанное время, но не выводит устройство из режима ожидания. Используется всемирное время UTC
- RTC_WAKEUP — выводит устройство из режима ожидания для запуска ожидающего намерения в указанное время. Используется всемирное время UTC
- triggerTime — время работы оповещения
- interval — интервал между отправкой повторных сигнализаций в миллисекундах. Также можно использовать константы
- INTERVAL_DAY
- INTERVAL_HALF_DAY
- INTERVAL_HOUR
- INTERVAL_HALF_HOUR
- INTERVAL_FIFTEEN_MINUTES
- operation — объект PendingIntent, определяющий действие, выполняемое при запуске сигнализации. Можно получить через специальные методы:
- PendingIntent.getActivities(Context, int, Intent[], int)
- PendingIntent.getActivity(Context, int, Intent, int)
- PendingIntent.getService(Context, int, Intent, int)
- PendingIntent.getBroadcast(Context, int, Intent, int)
Служба
Для установки сигнализации вам придётся создать собственную службу, наследуясь от базового класса Service (либо через приёмник BroadcastReceiver):
Запуск и управление службой происходит при помощи объекта Intent.
Установка времени для сигнализаций
Для задания времени работы оповещения необходимо установить его время запуска и добавить к нему длительность работы этого оповещения. Например, нам необходимо, чтобы оповещение отрабатывало 5 секунд после запуска:
Также можно использовать объект Calendar. Например, мы хотим, чтобы продолжительность сигнала оповещения была 10 секунд, а период повторения оповещения был один час:
Вы вошли на сайт, как гость.
Необходимо зарегистрироваться, чтобы прочитать статью
Источник
Полный список
— подробно разбираемся с PendingIntent
— используем AlarmManager
Перед тем, как продолжить тему виджетов, нам надо будет знать две темы: PendingIntent и AlarmManager.
С PendingIntent мы уже мельком встречались при работе с уведомлениями (Notifications) в Уроке 99. Вспомним, как создается этот объект. Мы создаем обычный Intent с нужными нам параметрами. Затем мы создаем PendingIntent каким-либо из методов: getActivity, getBroadcast, getService. Здесь имя метода определяет, какой тип объекта будет вызван с помощью нашего Intent. Ведь мы сами, когда отправляем Intent, явно говорим системе, что хотим вызвать: startActivity, sendBroadcast, startService.
Методы создания PendingIntent одинаковы по параметрам и требуют на вход:
context – тут все понятно.
requestCode – в хелпе почему-то написано «currently not used». Но при этом использовать их вполне можно. Это своего рода ключи, чтобы отличать один PendingIntent от других при необходимости.
intent – этот Intent будет впоследствии использован для вызова activity/broadcast/service (в зависимости от метода создания)
flags – флаги, влияющие на поведение и создание PendingIntent
Создавая и передавая другому приложению PendingIntent (с Intent внутри), мы предоставляем ему возможность и полномочия отправлять Intent от нашего имени. В этом уроке мы будем работать с PendingIntent. Увидим, что при создании есть свои нюансы, и разберемся, как можно использовать флаги и requestCode.
Вторая тема урока – AlarmManager. Это планировщик, которому можно передать PendingIntent и сказать, когда именно надо будет его использовать. В общем, что-то типа будильника. Там особо не о чем говорить, поэтому рассмотрим его совсем кратко.
PendingIntent
Создадим пример, в котором будем создавать различные PendingIntent и использовать их в Notifications. Результатом выполнения будет вызов BroadcastReceiver, в котором будем логировать входящую информацию.
Project name: P1191_PendingIntent
Build Target: Android 2.3.3
Application name: PendingIntent
Package name: ru.startandroid.develop.p1191pendingintent
Create Activity: MainActivity
Добавим строки в strings.xml:
Это наш Receiver, в который будут падать Intent из PendingIntent. В нем мы читаем Intent и выводим в лог action и один параметр из extra-данных. Не забудьте прописать этот класс в манифесте.
Только две кнопки.
Метод createIntent создает Intent с указанными параметрами.
Метод sendNotif создает уведомление с указанными ID и PendingIntent.
Метод compare выводит в лог результат сравнения Intent и PendingIntent. Для Intent используем метод filterEquals, который сравнивает Intent по action, data и пр., игнорируя extra-данные .
В onClick1 мы, используя все эти методы, будем создавать различные комбинации, и смотреть, что получается. Сейчас мы там создаем пару Intent и PendingIntent и просто сравниваем их, нигде не используя. В качестве флагов и requestCode мы пока используем нули.
В onClick2 пока ничего не пишем.
Все сохраним и запустим приложение.
Жмем Button1, смотрим лог.
intent1 = intent2: false
pIntent1 = pIntent2: false
Видим, что Intent-ы не равны (т.к. у них различается параметр action). А PendingIntent не равны потому, что их Intent не равны между собой.
Давайте теперь сравняем основные части Intent. Перепишем onClick1:
action будут равны, а Extra отличается. Сохраним, запустим. Жмем Button1:
intent1 = intent2: true
pIntent1 = pIntent2: true
Теперь метод filterEquals говорит нам, что Intent равны. Напомню – это потому, что этот метод не учитывает данные в Extra. PendingIntent получились равны, потому что (по версии filterEquals) равны их Intent. Этот момент надо четко понять, т.к. он очень сильно влияет на создание новых PendingIntent.
Попробую расписать алгоритм, как я его понимаю. Когда приложение создает PendingIntent, система его хранит в себе. При этом, Intent создаваемого PendingIntent сравнивается с Intent уже существующих PendingIntent. Если есть PendingIntent с Intent равным Intent создаваемого PendingIntent, то создаваемый PendingIntent получит этот существующий Intent. А Intent, с которым мы его пытались создать будет отброшен.
Т.е. в нашем случае мы создали pIntent1 с intent1, система его хранит. Далее мы создаем pIntent2 с intent2. Система проверяет существующие PendingIntent, и видит, что есть pIntent1 с intent1, и этот intent1 равен intent2. И ваш созданный pIntent2, теперь содержит intent1. А intent2 выкинут. pIntent1 при этом, разумеется, также остается со своим intent1. Просто теперь один Intent будет использоваться двумя PendingIntent-ами.
Можно сказать, что дефолтное поведение дает нам полную копию существующего PendingIntent, вместо создаваемого, если их Intent-ы равны без учета extra-данных.
Давайте убедимся в этом. Перепишем onClick1:
Будем создавать разные Intent, использовать их в PendingIntent и отправлять уведомления.
Все сохраним и запустим. Жмем Button1. Появились два уведомления.
Жмем первое (Title 1), смотрим лог:
onReceive
action = action 1
extra = extra 1
Все верно. Что помещали в intent1, то и получили в результате срабатывания pIntent1.
Жмем второе (Title 2) уведомление:
onReceive
action = action 2
extra = extra 2
Также все верно. Что помещали в intent2, то и получили в результате срабатывания pIntent2.
Теперь сделаем action одинаковым
Сохраняем, запускаем. Жмем Button1. Жмем первое уведомление:
onReceive
action = action
extra = extra 1
Жмем второе уведомление и наблюдаем в логах разрыв шаблона такое:
onReceive
action = action
extra = extra 1
При втором уведомлении сработал pIntent2, в который мы помещали intent2 c другим extra. Но получили мы extra из intent1. Причины описаны выше. Система увидела, что intent1 равен intent2 (без учета данных в Extra) и созданному pIntent2 дала intent1.
Это дефолтное поведение системы, но, к счастью, мы можем на него повлиять. Для этого и нужны флаги и requestCode, которые передаются в метод создания PendingIntent.
Флаги
Определимся с формулировкой. Фраза «создаваемый PendingIntent похож на существующий» означает, что равны (без extra) Intent-ы двух этих PendingIntent.
FLAG_CANCEL_CURRENT
Если система видит, что создаваемый с таким флагом PendingIntent похож на существующий, то она отменит (удалит) существующий.
Сохраняем, запускаем, жмем Button1, жмем первое уведомление. В логах ничего. pIntent1 был отменен системой в момент создания pIntent2, т.к. они похожи, а pIntent2 содержал флаг FLAG_CANCEL_CURRENT. И т.к. первое уведомление было создано с использованием pIntent1, оно ничего и не сделало.
Жмем второе уведомление.
onReceive
action = action
extra = extra 2
pIntent2 отменил pIntent1, но сам остался и выполнился.
FLAG_UPDATE_CURRENT
Этот флаг включает поведение, обратное дефолтному. Если система видит, что создаваемый с таким флагом PendingIntent похож на существующий, то она возьмет extra-данные Intent создаваемого PendingIntent и запишет их вместо extra-данных Intent существующего PendingIntent. Проще говоря, существующий PendingIntent будет использовать Intent из создаваемого.
Сохраняем, запускаем, жмем Button1, жмем первое уведомление. В логах:
onReceive
action = action
extra = extra 2
Видим, что pIntent1 использовал intent2 вместо intent1. Жмем второе уведомление :
onReceive
action = action
extra = extra 2
Данные из intent2. Получилось, что в обоих PendingIntent использовался intent2.
FLAG_ONE_SHOT
PendingIntent с этим флагом сработает лишь один раз. Сначала сделаем пример без флага. Перепишем onClick1:
Будем использовать один PendingIntent в обоих уведомлениях.
Сохраняем, запускаем, жмем Button1, жмем первое уведомление. В логах:
onReceive
action = action
extra = extra 1
жмем второе уведомление:
onReceive
action = action
extra = extra 1
Все логично. Оба уведомления использовали один pIntent1 с intent1.
Теперь используем флаг:
Этот флаг отменит PendingIntent после первого применения.
Сохраняем, запускаем, жмем Button1, жмем первое уведомление. В логах:
onReceive
action = action
extra = extra 1
Все ок, pIntent1 сработал. Жмем второе уведомление – в логах ничего. pIntent1 не сработал. Система увидела FLAG_ONE_SHOT и отменила PendingIntent после первого вызова. Т.е. PendingIntent с таким флагом может быть использован только один раз.
FLAG_NO_CREATE
PendingIntent не будет создан, если среди существующих нет похожего.
Перепишем onClick1 и onClick2
Сохраняем, запускаем. Жмем Button2, в логах:
pIntent2 is null
pIntent2 не создался, т.к. не было создано похожих PendingIntent. Дальнейшие нажатия будут возвращать тот же результат.
Теперь нажмем Button1, а затем Button2:
pIntent1 created
pIntent2 created
После создания pIntent1, получилось создать и pIntent2 (т.к. похожий pIntent1 существовал). Зачем нужен такой флаг? Единственное, что мне приходит в голову – с его помощью можно проверить существование в системе определенного PendingIntent. Если такой PendingIntent существует, то он вам и вернется (здесь действует дефолтное правило), а если не существует – то получим null.
Как оно там внутри работает
Наверняка назрели вопросы типа: где в системе хранятся эти PendingIntent, как долго они хранятся и когда отменяются (удаляются)?
К сожалению, не знаю. Самому было бы интересно узнать.
В последнем примере:
Если создать pIntent1, закрыть Activity, открыть Activity и создать pIntent2, то он создастся.
Если создать pIntent1, убить процесс, открыть Activity и создать pIntent2, то он создастся.
Если создать pIntent1, переустановить приложение, открыть Activity и создать pIntent2, то он не создастся.
Т.е. переустановка приложения точно скидывает все созданные в нем PendingIntent.
Если есть какие-нить мысли или ссылки на этот счет, пишите на форуме.
Отмена
Вы всегда можете вручную отменить любой PendingIntent методом cancel.
Все сохраним, запустим, жмем Button1. Появилось уведомление. Теперь жмем Button2. pIntent1 отменился. Но при этом, заметьте, уведомление спокойно продолжает себе висеть. Ему неважно, живой его PendingIntent или нет.
Нажимаем на уведомление и видим, что в логах ничего не происходит, т.к. PendingIntent был отменен.
requestCode
Что делать, если у нас есть Intent-ы, различающиеся только extra-данными, и нам все-таки нужно получить разные PendingIntent с ними? Можно использовать requestCode. При их использовании PendingIntent не будут считаться похожими, даже при равных Intent.
Используем requestCode = 1 для pIntent1 и 2 для pInten2.
Сохраняем, запускаем, жмем Button1. В логах:
intent1 = intent2: true
pIntent1 = pIntent2: false
Intent-ы равны, а PendingIntent-ы (благодаря requestCode) – нет.
Жмем первое уведомление
onReceive
action = action
extra = extra 1
Жмем второе уведомление
onReceive
action = action
extra = extra 2
Все сработало, как и ожидалось. Никто ни у кого Intent-ы не менял. Все остались при своих.
Есть еще вариант как сделать разные PendingIntent. Он подходит, если у вас в Intent не используется поле data. Туда можно поместить какие-то свои бессмысленные Uri, содержащие ID, которые просто будут разными, чтобы Intent-ы, а следовательно и PendingIntent-ы получились разными.
Либо можно, чтобы весь Intent преобразовывался в Uri и помещался в data. Делается это так:
Метод toUri преобразует Intent со всем его содержимым и всеми параметрами в строку. parse преобразует строку в Uri. Теперь даже если основные параметры Intent-ов будут одинаковы, то разное содержимое extra-данных сделает полученные Uri разными. И Intent-ы будут отличаться по полю data.
AlarmManager
Разобрались с PendingIntent. Взглянем на AlarmManager. Как я уже написал, да и как понятно из названия объекта, он отвечает за то, чтобы срабатывать по расписанию. «Срабатывать» означает использовать ваш PendingIntent, который вы ему отправите.
Два основных метода: set и setRepeating. Они позволяют запланировать, соответственно, разовое и повторяющееся событие.
Рассмотрим пример. Перепишем методы:
В onClick1 создадим два разных PendingIntent. Первый отправим методом set. На вход метод требует тип «будильника», время срабатывания (в милисекундах) и PendingIntent.
Типы будильника бывают следующие: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC и RTC_WAKEUP. В чем отличие между ними?
Те, название которых начинается с RTC, ориентируются на системное время. И время запуска таких будильников надо указывать относительно System.currentTimeMillis. Т.е. это RTC и RTC_WAKEUP.
Те, название которых начинается с ELAPSED_REALTIME, ориентируются на время от начала загрузки оси (включения устройства). Время запуска таких будильников надо указывать относительно SystemClock.elapsedRealtime(). Т.е. это ELAPSED_REALTIME и ELAPSED_REALTIME_WAKEUP.
Те, в названии которых есть WAKEUP, при срабатывании будут выводить устройство из спячки. Т.е. это ELAPSED_REALTIME_WAKEUP и RTC_WAKEUP.
Тут надо не путать спячку с выключенным экраном. Экран может быть выключен, но устройство вовсю будет работать. А когда задач нет устройство уходит в спячку, вырубая процессор для экономии энергии. Если будильники с типом не WAKEUP должны сработать, а устройство в это время спит, то их запуск откладывается до пробуждения. А WAKEUP-будильники разбудят устройство.
Вернемся к методу set. Используем здесь тип RTC, а, значит, время запуска (второй параметр метода) указываем относительно системного времени. Укажем текущее время + 4 секунды. Т.е. будильник сработает через 4 секунды после текущего времени создания. А когда он сработает, он выполнит pIntent1 (третий параметр метода).
Второй будильник ставим методом setRepeating. Он похож на set, только позволяет задать еще период повтора срабатывания. Для примера используем здесь тип ELAPSED_REALTIME. С таким типом время запуска мы должны указать, через сколько милисекунд после старта системы сработает будильник. Мы берем время уже прошедшее со старта (SystemClock.elapsedRealtime()), тем самым получая текущее время, и прибавляем к нему 3 секунды. Период повтора (третий параметр метода) сделаем равным 5 секунд. При срабатывании будет выполнен pIntent2.
Т.е. после того, как мы нажмем кнопку у нас установятся два будильника.
Первый – однократный, через 4 секунды от текущего времени, pIntent1.
Второй – повторяющийся каждые 5 сек., с первым запуском через 3 секунды от текущего времени.
В onClick2 мы будем выключать второй будильник, чтобы он у нас не работал вечно. Для этого выполняем метод cancel с указанием PendingIntent, который используется в будильнике.
Все сохраняем, запускаем приложение. Жмем Button1. В логах наблюдаем, как начали срабатывать будильники. Секунд через 20 жмем кнопку Button2, движуха в логах прекратилась. Смотрим логи:
07:55:22.380: start
07:55:25.450: onReceive
07:55:25.450: action = action 2
07:55:25.459: extra = extra 2
07:55:26.430: onReceive
07:55:26.430: action = action 1
07:55:26.430: extra = extra 1
07:55:30.499: onReceive
07:55:30.499: action = action 2
07:55:30.499: extra = extra 2
07:55:35.429: onReceive
07:55:35.429: action = action 2
07:55:35.429: extra = extra 2
07:55:40.450: onReceive
07:55:40.450: action = action 2
07:55:40.450: extra = extra 2
Второй будильник сработал через 3 секунды после старта и далее срабатывал каждые 5 сек, пока мы его не выключили методом cancel. А первый сработал один раз, через 4 секунды. Все, как и задумывалось.
Есть еще метод setInexactRepeating. Он аналогичен методу setRepeating, но периодичность его срабатывания не всегда точно такая, какую вы указали. Он может подстраивать запуск вашего будильника под будильники, которые будут выполнены примерно в то же время. Сделано это для экономии энергии, чтобы не будить два раза устройство, если оно спит. Судя по хелпу погрешность запуска может быть значительной, так что используйте аккуратнее.
Расскажу еще несколько полезных фактов из жизни будильников.
Если вы запланируете будильник с просроченным временем запуска – он выполнится сразу же.
После перезагрузки устройства все будильники стираются.
Если вы попытаетесь создать два разных будильника на основе одного или похожих PendingIntent, то сработает только второй, а первый будет удален при создании второго.
Создаем похожие PendingIntent и запланируем их в два разных будильника – через 2 и 4 секунды.
Сохраняем, запускаем. Жмем Button1. В логах видим:
8:04:03.740: action = action
8:04:03.750: extra = extra 1
Видим, что пришел Intent из pIntent1, который мы использовали для первого будильника, но пришел он через 4 секунды. Что произошло? Выше мы уже рассмотрели, что произойдет при создании похожих PendingIntent — второй будет использовать Intent первого. Кроме того AlarmManager определил, что pIntent1 (используемый в первом будильнике) и pIntent2 (используемый во втором) похожи, и решил, что негоже иметь разные будильники, с одинаковыми PendingIntent. И оставил нам только последний созданный будильник, т.е. второй.
Как решить проблему одинаковости PendingIntent, мы уже рассмотрели выше. Повторяться не буду.
Тема вроде несложная для понимания, но достаточно сложная для объяснения. Все аспекты и варианты рассмотреть в одном уроке трудновато, поэтому если у вас остались какие-либо вопросы, то самым лучшим способом получить ответы на них будут тесты.
На следующем уроке:
— обрабатываем нажатия на виджет
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник