【问题标题】:Alarm Manager - Scheduling multiple Non-repeating events警报管理器 - 安排多个非重复事件
【发布时间】:2011-07-11 11:27:20
【问题描述】:

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

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

如果我们在一个循环中设置不同的警报,那么它只保留最后一个。 我从帖子中读到:How can create more than one alarm?

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

我们需要在 Manifest 文件中添加什么来处理这个唯一的 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);
        }

如果需要更多详细信息或代码 sn-ps,请告诉我。

清单文件(此处为 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>

重复警报:

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

【问题讨论】:

    标签: android android-alarms


    【解决方案1】:

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

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

    (1) 首先,Manifest 文件: 确保您的班级拥有 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) Activity 类,您将在其中使用 AlarmManager 来安排警报: 我正在使用数据库来存储我的闹钟时间值,然后使用这些值进行调度。我的光标从表中获取唯一的 _ID 和警报时间(自 1970 年 1 月 1 日以来的秒数)。看到放在这里的 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 类。

    【讨论】:

    • 对我来说关键是这一行:intent.setData(Uri.parse("timer:" + notifCursor.getInt(0)));这确保了意图是唯一的,并且对 AlarmManager.set 的后续调用不会取消之前的意图。
    • 谢谢@JonathonHorsman 我创建了这个little class 是为了给我独特的新值,线程保存并将它们保存在共享首选项中(这样即使你的应用程序被杀死,它也可以恢复)。跨度>
    【解决方案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);
    }
    

    对我来说工作得很好。

    【讨论】:

    • 使用 Intent.FLAG_GRANT_READ_URI_PERMISSION 时出现错误 - 类型不正确。我知道我需要设置该标志,以便我可以在 onReceive 中使用 intent.getData().getSchemeSpecificPart()
    猜你喜欢
    • 1970-01-01
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-17
    相关资源
    最近更新 更多