Alarm Manager - планирование нескольких неповторяющихся событий - PullRequest
24 голосов
/ 11 июля 2011

В Android Alarm Manager, как мы можем запланировать несколько сигналов, которые не повторяются и не имеют фиксированных интервалов для повторения? Я не могу использовать функцию 'setRepeating', так как у аварийных сигналов нет повторяющегося шаблона.

У меня есть время будильника, хранящееся в таблице базы данных Sqlite, и действие должно выбрать дату и время из этой таблицы и установить будильники.

Если мы устанавливаем разные сигналы в цикле, то он сохраняет только последний. Я прочитал из поста: Как можно создать более одного будильника?

Указывает присоединить уникальный идентификатор к намерению, а затем настроить отдельные события тревоги. Но это не сработало для меня.

Что нам нужно добавить в файл манифеста, чтобы позаботиться об этом уникальном идентификаторе?

Код в операции «RegularSchedule» есть, и он создает только одно аварийное событие:

        while (notifCursor.moveToNext()) {
            Intent intent = new Intent(RegularSchedule.this,
                    RepeatingAlarm.class);

            // The cursor returns first column as unique ID             
            intent.setData(Uri.parse("timer:" + notifCursor.getInt(0)));

            PendingIntent sender = PendingIntent.getBroadcast(
                    RegularSchedule.this, 0, intent, 0);

            // Setting time in milliseconds taken from database table 
            cal.setTimeInMillis(notifCursor.getLong(1));

            AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
        }

Пожалуйста, дайте мне знать, если требуется дополнительная информация или фрагменты кода.

Файл манифеста (здесь RepeatingAlarm расширяет BroadcastReceiver):

    <receiver android:name=".user_alerts.RepeatingAlarm" android:process=":remote" />

    <activity android:name=".user_alerts.RegularSchedule"
        android:label="@string/reg_schedule_title" android:theme="@android:style/Theme.Light">
    </activity>

RepeatingAlarm:

public class RepeatingAlarm extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
.......
    // The PendingIntent to launch our activity if the user selects this notification
    Intent notificationIntent = new Intent (context, DisplayReminder.class);
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

    // Set the info for the views that show in the notification panel.
    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
    notification.defaults |= Notification.DEFAULT_SOUND;
    notification.defaults |= Notification.DEFAULT_VIBRATE;
    notification.defaults |= Notification.DEFAULT_LIGHTS;

    mNotificationManager.notify(2425, notification);

Ответы [ 2 ]

28 голосов
/ 13 июля 2011

Вот что у меня сработало.Я делюсь этим решением, чтобы другие могли извлечь выгоду и быстро найти решение этой проблемы.

Я приветствую любые другие материалы, чтобы пролить больше света на технические аспекты решения и на то, почему некоторые вещи работают, а другие нет.:)

(1) Прежде всего, файл манифеста: убедитесь, что у вас есть получатель для вашего класса с BroadcastReceiver.

    <receiver android:name=".RepeatingAlarm" android:process=":remote">
        <intent-filter>
            <data android:scheme="timer:" />
        </intent-filter>
    </receiver>

Обратите внимание, что класс является частью основного пакета.Если он находится в каком-либо субпакете, перейдите в основной пакет.Основной пакет - это то, что вы определяете в теге manifest.

'intent-filter' используется для определения 'action' и 'data'.Здесь вы можете поместить класс Activity, который будет вызываться из вашего ожидаемого намерения.Но я обнаружил, что если вы определяете «действие» в манифесте, оно не отображает динамические значения в действии.Это просто показывает статические значения.Довольно странно.Если вы столкнулись с той же проблемой, не помещайте 'action' в манифест, а поместите его в класс BroadcastReceiver как часть ожидаемого намерения.

тег 'data' - это то, что вы собираетесь поместить динамический URI уникальногонамерения при планировании различных сигналов тревоги с помощью AlarmManager.Пожалуйста, обратитесь к следующим шагам для получения более подробной информации.

(2) Класс деятельности, в котором вы собираетесь использовать AlarmManager для планирования тревог: я использую базу данных для хранения значений времени будильника, а затем планирую их использование.Мой курсор выбирает уникальный _ID из таблицы и время будильника (в секундах с 01.01.1970).Обратите внимание, что указанный здесь URI совпадает с тем, что имеется в файле манифеста.

    Calendar cal = Calendar.getInstance();
    int notifIterator = 0;

    if (notifCursor.getCount() > 0) {
        while (notifCursor.moveToNext()) {
            Intent intent = new Intent(MySchedule.this,
                    RepeatingAlarm.class);

            // As the same intent cancels the previously set alarm having
            // same intent
            // changing the intent for every alarm event so that every alarm
            // gets
            // scheduled properly.
            intent.setData(Uri.parse("timer:" + notifCursor.getInt(0)));

            PendingIntent sender = PendingIntent.getBroadcast(
                    MySchedule.this, 0, intent,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION);

            cal.setTimeInMillis(notifCursor.getLong(1) * 1000);

            AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);

            notifIterator++;

            Toast mToast = Toast.makeText(
                    RegularSchedule.this,
                    "Reminders added to the calendar successfully for "
                            + android.text.format.DateFormat.format(
                                    "MM/dd/yy h:mmaa",
                                    cal.getTimeInMillis()),
                    Toast.LENGTH_LONG);
            mToast.show();
        }
    }

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

(3) Последним является класс BroadcastReceiver.Обратите внимание, что для открытия базы данных вам потребуется использовать контекст:

public void onReceive(Context context, Intent intent) {

    // Update the status in the notification database table
    int notificationId = Integer.parseInt(intent.getData().getSchemeSpecificPart());

    db = context.openOrCreateDatabase(DATABASE_NAME,
            SQLiteDatabase.CREATE_IF_NECESSARY, null);

    <<<< Do DB stuff like fetching or updating something>>>>

    // Raise the notification so that user can check the details
    NotificationManager mNotificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);

    int icon = R.drawable.icon;
    CharSequence tickerText = "your text";
    long when = System.currentTimeMillis();

    Notification notification = new Notification(icon, tickerText, when);

    // Count of number of notifications
    notification.number = notifCount;

    CharSequence contentTitle = "your title ";
    CharSequence contentText = "your notification text";

    // The PendingIntent to launch our activity if the user selects this
    // notification
    Intent notificationIntent = new Intent(context, DisplayReminder.class);
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
            notificationIntent, 0);


    // Set the info for the views that show in the notification panel.
    notification.setLatestEventInfo(context, contentTitle, contentText,
            contentIntent);
    notification.defaults |= Notification.DEFAULT_SOUND;
    notification.defaults |= Notification.DEFAULT_VIBRATE;
    notification.defaults |= Notification.DEFAULT_LIGHTS;

    // Instead of 1234 or any other number, use below expression to have unique notifications
    // Integer.parseInt(intent.getData().getSchemeSpecificPart())
    mNotificationManager.notify(1234, notification);
}

Обратите внимание, что если вы хотите создать отдельное уведомление, идентификатор запроса может быть передан как уникальный при вызове notify ().

Наконец, вы можете создать класс DisplayReminder, который вы хотите вызывать, когда пользователь нажимает на уведомление.

1 голос
/ 07 февраля 2015

Как подсказал @Jonathon Horsman, убедитесь, что создаваемые вами намерения уникальны.

Если вы хотите установить, например, 10 будильников:

for(int i=; i<10; i++) {
   Intent intent = new Intent(YourActivity.this,
                YourAlarm.class);
   intent.setData(Uri.parse("timer:" + i);
   PendingIntent sender = PendingIntent.getBroadcast(
                YourActivity.this, 0, intent,
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
   AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
   am.set(AlarmManager.RTC_WAKEUP, yourTimeInMillis, sender);
}

Работает нормально.

...