Подтвердить что ты не робот

Alarm Manager - Планирование нескольких неповторяющихся событий

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

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

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

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

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

Код в действии "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);
4b9b3361

Ответ 1

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

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

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

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

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

'target-filter' используется для определения "действия" и "данных". Здесь вы можете поместить класс Activity, который будет вызван из вашего ожидающего намерения. Но я обнаружил, что если вы определяете "действие" в манифесте, оно не отображает динамические значения в активности. Он просто показывает статические значения. Довольно странно. Если вы попадаете в одну и ту же проблему, не помещайте "действие" в манифест, скорее поместите его в класс 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. Обратите внимание, что для открытия базы данных вам потребуется использовать "context":

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, который вы хотите вызвать, когда пользователь нажимает на уведомление.

Ответ 2

Как было предложено @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);
}

Работал хорошо для меня.