在特定时间创建通知

Creating a notification at a specific time

我有一个正在开发的日历应用程序,我需要提醒用户即将发生的事件。

所以我想知道这样做的最佳做法是什么,我应该怎么做,因为我目前的解决方案甚至都不是很好。

我现在的做法是使用 AlarmManager 触发创建并显示通知的 BroadcasReciever。

我需要使用服务吗?如果可以,我应该怎么做?

代码:

    private void StartDBUpdateAlarm() // Start the alarm manager for event reminder 
    {
        // Get the eventos orded by date (Later than DateTime.Now),
        // so that we can get the earliest events
        var eventos = eventDao.Select(FromEventos.OrderByDate, DateTime.Now);

        if ((eventos.Count > 0)) // Only create notification if there is an event
        {
            // Create the Intent to pass some info through it to the notification
            Intent alarmIntent = new Intent(this, typeof(ReminderReciever));

            // Putting the information that will be passed with constant Id's  
            alarmIntent.PutExtra(GerirUtils.INTENT_TITLE, GetString(Resource.String.main_notification_title));
            alarmIntent.PutExtra(GerirUtils.INTENT_INFO, "Info");
            alarmIntent.PutExtra(GerirUtils.INTENT_CONTENT, eventos[0].Descricao);

            // Creating/Recreating the Pending Intent that will pass the actual information to the notification
            PendingIntent pendingIntent = PendingIntent.GetBroadcast(this, GerirUtils.NOTIFICATION_REMINDER_ID, alarmIntent, 0);

            // Getting the date and time of the next event, then calculate the diference between DateTime.Now,
            // to know how much time it'll be until next event, so that we know when to trigger the notification
            DateTime eventDateTime = CalendarHelper.EventDateTime(eventos[0]);                
            TimeSpan eventMillis = (eventDateTime - GerirUtils.BaseUTCDate); // BaseDate is just the Utc date = 1970/01/01, because the alarm counts millis since then

            // Creating and setting the alarm manager
            alarm = (AlarmManager)GetSystemService(Context.AlarmService);
            alarm.SetExact(AlarmType.RtcWakeup, (long)eventMillis.TotalMilliseconds, pendingIntent);
        }
    }

广播接收器CLASS

[BroadcastReceiver(Enabled = true)]
public class ReminderReciever : BroadcastReceiver
{
    private string type, title, info, content;
    private IList<string> events;
    private int notificationId;
    private Context context;

    public override void OnReceive(Context context, Intent intent)
    {
        this.context = context;
        notificationId = intent.GetIntExtra(GerirUtils.INTENT_ID, -1);
        type           = intent.GetStringExtra(GerirUtils.INTENT_TYPE);
        events         = intent.GetStringArrayListExtra(GerirUtils.INTENT_EVENTS);

        title    = intent.GetStringExtra(GerirUtils.INTENT_TITLE);
        info     = intent.GetStringExtra(GerirUtils.INTENT_INFO);
        content  = intent.GetStringExtra(GerirUtils.INTENT_CONTENT);


        if(notificationId > -1)
            if(type == GerirUtils.NOTIFICATION_TYPE_EVENT_REMINDER)
                ShowNotification();
            else if(type == GerirUtils.NOTIFICATION_TYPE_ADDED_EVENTS)
                ShowNotificationList();
    }

    private void ShowNotification() 
    {
        Android.Net.Uri sound = RingtoneManager.GetDefaultUri(RingtoneType.Alarm);
        NotificationManager mNotificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);

        if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
        {
            NotificationChannel channel = new NotificationChannel("default", title, NotificationImportance.Default) { Description = content };
            mNotificationManager.CreateNotificationChannel(channel);
        }

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, "default")
                    .SetSmallIcon(Resource.Mipmap.ic_calendario_gerir) // notification icon
                    .SetContentTitle(title)  // title for notification
                    .SetContentText(content) // message for notification
                    .SetContentInfo(info)    // Info message next to content
                    .SetSound(sound)         // set alarm sound for notification
                    .SetAutoCancel(true);    // clear notification after click

        Intent intent = new Intent(context, typeof(MainActivity));

        PendingIntent pi = PendingIntent.GetActivity(context, 0, intent, PendingIntentFlags.UpdateCurrent);
        mBuilder.SetContentIntent(pi);
        mNotificationManager.Notify(0, mBuilder.Build());
    }
}

嗯,仔细检查代码后我设法找到了问题,看起来我没有通过意图发送 notificationId。 BroadcastReviever 上的意图始终是默认的 -1,所以 if 语句始终是假的,而且,愚蠢的我,当 ID 为 -1 时没有发出消息警告,所以我很难找到错误然后如果我收到消息我会怎么做。

因此,解决方案是将这行代码添加到程序中:

private void StartDBUpdateAlarm() // Start the alarm manager for event reminder 
{
    ...
    ...

    if ((eventos.Count > 0)) // Only create notification if there is an event
    {
        // Create the Intent to pass some info through it to the notification
        Intent alarmIntent = new Intent(this, typeof(ReminderReciever));

        // MISSING LINE OF CODE
        alarmIntent.PutExtra(GerirUtils.INTENT_ID, GerirUtils.NOTIFICATION_REMINDER_ID);
        ...
        ...
        ...            
    }
}