警报管理器 - 安排多个非重复事件

发布于 2024-11-19 07:50:44 字数 2485 浏览 7 评论 0原文

在Android闹钟管理器中,我们如何安排多个不重复且没有固定重复时间间隔的闹钟?我无法使用“setRepeating”功能,因为警报没有任何重复模式。

我将闹钟时间存储在 Sqlite 数据库表中,活动应该从该表中选择日期和时间并设置闹钟。

如果我们循环设置不同的闹钟,那么它只保留最后一个。 我从帖子中读到:如何创建多个警报?

它指示将唯一的 ID 附加到意图,然后设置单独的警报事件。但这对我不起作用。

我们是否需要在清单文件中添加一些内容来处理这个唯一的 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);

In Android Alarm Manager, how can we schedule multiple alarms which are non-repeating and do not have fixed intervals to repeat? I cannot use 'setRepeating' function as the alarms don't have any repeating pattern.

I have the alarm times stored in Sqlite database table and the activity should pick the date and time from this table and set the alarms.

If we setup different alarms in a loop, then it retains only the last one.
I read from the post: How can create more than one alarm?

It tells to attach the unique Id to the intent and then setting up individual alarm events. But it didn't work for me.

Is there something we need to add in Manifest file to take care of this unique id?

The code in the activity 'RegularSchedule' is and it creates only one alarm event:

        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);
        }

Please let me know if further details or code snippets are required.

Manifest file (here RepeatingAlarm extends 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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

临风闻羌笛 2024-11-26 07:50:45

这对我有用。我正在分享解决方案,以便其他人能够受益并找到解决此问题的快速解决方案。

我欢迎任何其他意见,以更多地了解解决方案的技术性以及为什么某些事情有效而其他事情不起作用:)

(1) 首先,清单文件:
确保您的班级有具有 BroadcastReceiver 的接收器。

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

请注意,该类是主包的一部分。如果它在某个子包中,请移至主包。主包是您在“manifest”标签中定义的内容。

“intent-filter”用于定义“action”和“data”。您可以将 Activity 类放在此处,该类将从您的挂起意图中调用。但我发现,如果您在清单中定义“操作”,它不会显示活动的动态值。它仅显示静态值。很奇怪。如果您遇到同样的问题,请勿将“操作”放入清单中,而是将其放入 BroadcastReceiver 类中作为待处理意图的一部分。

“data”标签是您在使用 AlarmManager 调度不同警报时要放置的唯一意图的动态 URI。请参阅后续步骤了解更多详细信息。

(2) 您将在其中使用 AlarmManager 来安排警报的 Activity 类:
我使用数据库来存储闹钟时间值,然后使用这些值进行调度。我的游标从表中获取唯一的 _ID 和闹钟时间(自 1970 年 1 月 1 日起以秒为单位)。请注意此处放置的 URI 与清单文件中的 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 时区。如果你查看 toast 消息,这将帮助你解决这个问题。

(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()时可以将请求ID作为唯一的传递。

最后,您可以创建当用户单击通知时要调用的 DisplayReminder 类。

This is what worked for me. I'm sharing the solution so that others can benefit and find quick solution to this problem.

I welcome any other inputs to throw more light on the technicality of the solution and why certain things work and others don't :)

(1) First of all, Manifest file:
Make sure that you have receiver for your class having BroadcastReceiver.

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

Please note that the class is part of main package. If it is in some sub-package, please move to the main package. The main package is what you define in 'manifest' tag.

'intent-filter' is used to define 'action' and 'data'. You can put the Activity class here which is going to be called from your pending intent. But I found that if you define 'action' in manifest, it doesn't display dynamic values on the activity. It just shows static values. Quite strange. If you get in same issue, don't put 'action' in manifest, rather put it in BroadcastReceiver class as part of pending intent.

'data' tag is what you are going to put dynamic URI of unique intents while scheduling different alarms using AlarmManager. Please refer next steps for more details.

(2) Activity Class in which you are going to use AlarmManager to schedule alarms:
I'm using the database to store my alarm time values and then scheduling using those values. My cursor fetches the unique _ID from the table and alarm time (in seconds since 1/1/1970). See that the URI put here is same as what you have in manifest file.

    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();
        }
    }

If you don't see alarms even after doing this, check the timezone which emulator takes. Sometimes, we schedule for Local Timezone, but emulator schedules for GMT timezone. If you look at toast message, that will help you figure out this problem.

(3) Last one is BroadcastReceiver class. Please note that to open database, you will require to use the '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);
}

Note that if you want to create separate notification, the request id can be passed as unique when calling notify().

Finally, you can create DisplayReminder class which you want to call when user clicks on notification.

赠我空喜 2024-11-26 07:50:45

正如@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);
}

对我来说效果很好。

As suggested @Jonathon Horsman, make sure that the intents you're creating are unique.

If you want to set 10 alarms for example :

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);
}

Worked fine for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文