Android: Як користуватися AlarmManager


89

Мені потрібно запустити блок коду через 20 хвилин після AlarmManagerвстановлення.

Хтось може показати мені зразок коду про те, як користуватися AlarmManagerin Android?

Я кілька днів бавився з якимсь кодом, і він просто не буде працювати.

Відповіді:


109

"Якийсь зразок коду" не так простий, коли справа доходить AlarmManager.

Ось фрагмент, що показує налаштування AlarmManager:

AlarmManager mgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, OnAlarmReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);

mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), PERIOD, pi);

У цьому прикладі я використовую setRepeating(). Якщо вам потрібен одноразовий сигнал, ви просто скористаєтесь ним set(). Обов’язково дайте час для спрацювання будильника в тій самій часовій базі, що і в початковому параметрі до set(). У наведеному вище прикладі я використовую AlarmManager.ELAPSED_REALTIME_WAKEUP, тому моя часова база така SystemClock.elapsedRealtime().

Ось більший зразок проекту, що демонструє цю техніку.


2
Привіт знову. Дякую за відповідь. Якщо я купую вашу книгу, чи пояснюється це, як впровадити менеджер сигналізації з усіма деталями?
Том

7
У книзі Advanced Android (версія 0.9) є ~ 9 сторінок, що охоплюють AlarmManager, WakeLocks та решту цього прикладу. Це, ймовірно, трохи розшириться у версії 1.0, коли я роблю виправлення, яке я згадав у своїй відповіді вище. А якщо у вас є запитання щодо книги чи її зразка коду, перейдіть до groups.google.com/group/cw-android, і я з радістю відповім на них.
CommonsWare

17
Будь-який розробник Android повинен мати передплату на книги Марка :) Принаймні один раз
Бостон

1
@ MarioGalván: Вам потрібно встановити його, коли ваш додаток запускається вперше та під час перезавантаження.
CommonsWare

Я думаю, вам слід використовувати AlarmManager.RTC_WAKEUP, якщо ви хочете, щоб він запускався відразу, а потім кожен ПЕРІОД. У вашому коді він запускатиметься після SystemClock.elapsedRealtime (), а потім кожного ПЕРІОДУ.
Деймон Юань,

66

У прикладі коду для android є кілька хороших прикладів

. \ android-sdk \ sample \ android-10 \ ApiDemos \ src \ com \ example \ android \ apis \ app

Ось, кого слід перевірити:

  • AlarmController.java
  • OneShotAlarm.java

По-перше, вам потрібен приймач, щось, що може прослуховувати ваш будильник, коли він спрацьовує. Додайте наступне у свій файл AndroidManifest.xml

<receiver android:name=".MyAlarmReceiver" />

Потім створіть наступний клас

public class MyAlarmReceiver extends BroadcastReceiver { 
     @Override
     public void onReceive(Context context, Intent intent) {
         Toast.makeText(context, "Alarm went off", Toast.LENGTH_SHORT).show();
     }
}

Потім, щоб спрацьовувати будильник, використовуйте наступне (наприклад, у вашій основній діяльності):

AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
Calendar time = Calendar.getInstance();
time.setTimeInMillis(System.currentTimeMillis());
time.add(Calendar.SECOND, 30);
alarmMgr.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pendingIntent);

.


Або, ще краще, створити клас, який все це обробляє, і використовувати його таким чином

Bundle bundle = new Bundle();
// add extras here..
MyAlarm alarm = new MyAlarm(this, bundle, 30);

таким чином, у вас все це в одному місці (не забудьте відредагувати AndroidManifest.xml)

public class MyAlarm extends BroadcastReceiver {
    private final String REMINDER_BUNDLE = "MyReminderBundle"; 

    // this constructor is called by the alarm manager.
    public MyAlarm(){ }

    // you can use this constructor to create the alarm. 
    //  Just pass in the main activity as the context, 
    //  any extras you'd like to get later when triggered 
    //  and the timeout
     public MyAlarm(Context context, Bundle extras, int timeoutInSeconds){
         AlarmManager alarmMgr = 
             (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
         Intent intent = new Intent(context, MyAlarm.class);
         intent.putExtra(REMINDER_BUNDLE, extras);
         PendingIntent pendingIntent =
             PendingIntent.getBroadcast(context, 0, intent, 
             PendingIntent.FLAG_UPDATE_CURRENT);
         Calendar time = Calendar.getInstance();
         time.setTimeInMillis(System.currentTimeMillis());
         time.add(Calendar.SECOND, timeoutInSeconds);
         alarmMgr.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(),
                      pendingIntent);
     }

      @Override
     public void onReceive(Context context, Intent intent) {
         // here you can get the extras you passed in when creating the alarm
         //intent.getBundleExtra(REMINDER_BUNDLE));

         Toast.makeText(context, "Alarm went off", Toast.LENGTH_SHORT).show();
     }
}

2
Привіт! Я протестував цей код, і він працює нормально (+1). але я спробував це для кількох будильників (наприклад, один на 10 секунд, а інший на 15, і спрацьовує лише другий. Чи я роблю щось неправильно, чи це якась проблема? EDIT: Добре, я знайшов проблему тут : stackoverflow.com/questions/2844274/…
Нуно Гонсалвес,

FWIW, для цього я скористався статичним методом, а не конструктором.
Едвард Фальк

9

Що вам потрібно зробити, це спочатку створити намір, який вам потрібно запланувати. Потім отримайте pendingIntent цього наміру. Ви можете запланувати діяльність, послуги та трансляції. Щоб запланувати діяльність, наприклад MyActivity:

  Intent i = new Intent(getApplicationContext(), MyActivity.class);
  PendingIntent pi = PendingIntent.getActivity(getApplicationContext(),3333,i,
  PendingIntent.FLAG_CANCEL_CURRENT);

Подайте цей очікуваний намір alarmManager:

  //getting current time and add 5 seconds in it
  Calendar cal = Calendar.getInstance();
  cal.add(Calendar.SECOND, 5);
  //registering our pending intent with alarmmanager
  AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
  am.set(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), pi);

Тепер MyActivity буде запущено через 5 секунд після запуску програми, незалежно від того, чи ви зупиняєте програму чи пристрій переходить у режим сну (через опцію RTC_WAKEUP). Ви можете прочитати повний приклад коду Планування діяльності, послуг та трансляцій #Android


+1 чудова відповідь, саме те, що мені потрібно, приклад робочого "набору".
A.Alqadomi

4

Я хотів прокоментувати, але <50 повторень, тому тут йдеться. Дружнє нагадування: якщо ви працюєте на версії 5.1 або новішій і використовуєте інтервал менше хвилини, трапляється таке:

Suspiciously short interval 5000 millis; expanding to 60 seconds

Дивіться тут .


3

Деякі зразки коду, коли ви хочете зателефонувати до служби з Alarmmanager:

PendingIntent pi;
AlarmManager mgr;
mgr = (AlarmManager)ctx.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(DataCollectionActivity.this, HUJIDataCollectionService.class);    
pi = PendingIntent.getService(DataCollectionActivity.this, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() , 1000, pi);

Вам не потрібно запитувати дозволи користувача.


Дуже поширене скорочення.
Phantômaxx

0

AlarmManager використовується для запуску деякого коду в певний час.

Щоб запустити менеджер тривог, вам потрібно спочатку отримати екземпляр із системи. Потім передайте PendingIntent, який буде виконаний у майбутній час, який ви вказали

AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

Intent alarmIntent = new Intent(context, MyAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
int interval = 8000; //repeat interval
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);

Потрібно бути обережним під час використання диспетчера сигналів. Зазвичай менеджер будильників не може повторити це за хвилину. Також у режимі низької потужності тривалість може збільшитися до 15 хвилин.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.