AlarmManager仅适用于不久的将来

时间:2015-06-16 14:44:53

标签: android xamarin alarmmanager xamarin.forms

我正在开发适用于Android,iOS和Windows Phone的Xamarin应用。此应用应在指定时间显示本地通知。对于Android我使用AlamManager。通知适用于iOS,WinPhone和Android Emulators。在我的设备(三星Galaxy S2)上,仅在近期(1分钟,5分钟,20分钟)通知工作。不会出现约45分钟或更长时间的通知。有时会出现约30分钟的通知,有时也不会出现。通知在广播接收器中进行。我的代码或alarmManager有问题吗?找不到任何东西。谢谢你的帮助。

这里设置了alarmManager:

public class NotificationService : NotificationServiceBase
{
    private readonly AlarmManager _alarmManager;
    private readonly long _dayInMilliseconds = AlarmManager.IntervalDay;
    private PendingIntent _currentPendingIntent;

    public NotificationService()
    {
        _alarmManager = (AlarmManager) Forms.Context.GetSystemService(Context.AlarmService);
    }

    public override void CancelNotification()
    {
        _alarmManager.Cancel(_currentPendingIntent);
    }

    protected override void ChangeNotificationTime(TaskEntity task)
    {
        var settings = _settingsBusinessLayer.GetSettings();
        NotificationSetup(settings, task);
    }

    protected override async void ChangeNotificationSettings(SettingsEntity settings)
    {
        if (!settings.IsReminderOn)
        {
            CancelNotification();
            return;
        }

        var task = await _taskBusinessLayer.GetTaskForCurrentMonthAsync(true, true);
        NotificationSetup(settings, task);
    }

    private void NotificationSetup(SettingsEntity settings, TaskEntity task)
    {
        _currentPendingIntent = GetPendingIntent();
        _alarmManager.Cancel(_currentPendingIntent);

        if (settings.ReminderRepetitive == ReminderRepetitive.Daily)
        {
            SetDailyAlarm(settings);
        }
        else
        {
            SetSingleAlarm(settings, task);
        }
    }

    private void SetDailyAlarm(SettingsEntity settings)
    {
        long alarmTimeInMilliseconds;

        if (settings.RemindOn < DateTime.Now.TimeOfDay)
        {
            alarmTimeInMilliseconds = (long) CalculateAlarmTimeFromNow
                (DateTime.Now.AddDays(1), 0, settings.RemindOn).TotalMilliseconds;
        }
        else
        {
            alarmTimeInMilliseconds = (long) CalculateAlarmTimeFromNow
                (DateTime.Now, 0, settings.RemindOn).TotalMilliseconds;
        }

        var alarmTime = SystemClock.ElapsedRealtime() + alarmTimeInMilliseconds;
        _alarmManager.SetRepeating(AlarmType.ElapsedRealtime, alarmTime, _dayInMilliseconds, _currentPendingIntent);
    }

    private void SetSingleAlarm(SettingsEntity settings, TaskEntity task)
    {
        try
        {
            var alarmTimeInMilliseconds = (long) CalculateAlarmTimeFromNow
                (task.DueDate, Convert.ToUInt32(settings.RemindDaysBefore), settings.RemindOn).TotalMilliseconds;
            var alarmTime = SystemClock.ElapsedRealtime() + alarmTimeInMilliseconds;
            _alarmManager.Set(AlarmType.ElapsedRealtime, alarmTime, _currentPendingIntent);
        }
        catch (AlarmTimeIsInPastException)
        {
        }
    }

    private PendingIntent GetPendingIntent()
    {
        var alarmIntent = new Intent(Forms.Context, typeof (NotificationReceiver));
        return PendingIntent.GetBroadcast(Forms.Context, 0, alarmIntent,
            PendingIntentFlags.UpdateCurrent);
    }
}

广播接收器,发出通知。

[BroadcastReceiver]
public class NotificationReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        var taskBusinessLayer = DependencyInjection.Container.Resolve<ITaskBusinessLayer>();
        var task = taskBusinessLayer.GetTaskForCurrentMonthAsync(true, true).Result;
        var message = NotificationServiceBase.CreateNotificationMessageRemainingTime(task);
        var title = AppResources.NotificationTitle;
        var notIntent = new Intent(context, typeof (MainActivity));
        var contentIntent = PendingIntent.GetActivity(context, 0, notIntent, PendingIntentFlags.CancelCurrent);

        var builder = new Notification.Builder(context)
            .SetContentIntent(contentIntent)
            .SetContentTitle(title)
            .SetContentText(message)
            .SetSmallIcon(Resource.Drawable.icon)
            .SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate)
            .SetPriority((int) NotificationPriority.Max)
            .SetAutoCancel(true)
            .SetWhen(JavaSystem.CurrentTimeMillis());

        var notification = builder.Build();
        var notificationManager = NotificationManager.FromContext(context);

        const int notificationId = 0;
        notificationManager.Notify(notificationId, notification);
    }

}

1 个答案:

答案 0 :(得分:0)

从KITKAT开始的警报传递是不准确的。所以你可能需要改变你的SetSingleAlarm方法:

_alarmManager.Set(AlarmType.ElapsedRealtime, alarmTime, _currentPendingIntent);

到此:

if (Build.VERSION.SdkInt < BuildVersionCodes.Kitkat)
{
    _alarmManager.Set(AlarmType.ElapsedRealtime, alarmTime, _currentPendingIntent);
}
else
{
    _alarmManager.SetExact(AlarmType.ElapsedRealtime, alarmTime, _currentPendingIntent);
}