426 lines
18 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Foundation;
using UIKit;
using UserNotifications;
namespace gehGassi.LocalNotifications.Platforms
{
public class NotificationService : UNUserNotificationCenterDelegate, INotificationService, IUNUserNotificationCenterDelegate
{
public static readonly NSString TITLE = new NSString("Title");
public static readonly NSString BODY = new NSString("Body");
public static readonly NSString NOTIFICATION_ID = new NSString("NoticationId");
public static readonly NSString NOTIFICATION_ID_FIREBASE = new NSString("notification_id");
public static readonly NSString PAYLOAD = new NSString("Payload");
public static readonly NSString PAYLOAD_FIREBASE = new NSString("data");
public static readonly NSString PRESENT_ALERT = new NSString("PresentAlert");
public static readonly NSString PLAY_SOUND = new NSString("PlaySound");
public static readonly NSString SOUND = new NSString("Sound");
public static readonly NSString SHOW_BADGE = new NSString("ShowBadge");
public static readonly NSString BADGE_NUMBER = new NSString("BadgeNumber");
public static readonly NSString NOTIFICATION_LAUNCHED_APP = new NSString("NotificationLaunchedApp");
public static readonly NSString NOTIFICATION_REQUEST = new NSString("NotificationRequest");
public static readonly NSString NOTIFICATION_ISLOCAL = new NSString("NotificationIsLocal");
public NotificationService()
{
}
public static void Initialize(NSDictionary options)
{
UNUserNotificationCenter.Current.Delegate = new LocalNotificationDelegate();
}
private static NotificationTappedEventHandler onNotificationTapped;
public event NotificationTappedEventHandler OnNotificationTapped
{
add => onNotificationTapped += value;
remove => onNotificationTapped -= value;
}
public static void OnPlatformNotificationTapped(string payload, int? notificationId, bool isLocal)
{
NotificationEventArgs e = new NotificationEventArgs()
{
NotificationId = notificationId,
Payload = payload,
IsLocal = isLocal
};
onNotificationTapped?.Invoke(e);
}
private static NotificationReceivedEventHandler onNotificationReceived;
public event NotificationReceivedEventHandler OnNotificationReceived
{
add => onNotificationReceived += value;
remove => onNotificationReceived -= value;
}
public static void OnPlatformNotificationReceived(string payload, int? notificationId, bool isLocal)
{
NotificationEventArgs e = new NotificationEventArgs()
{
NotificationId = notificationId,
Payload = payload,
IsLocal = isLocal
};
onNotificationReceived?.Invoke(e);
}
public void RegisterForPushNotifications()
{
// Register your app for remote notifications.
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = new LocalNotificationDelegate();
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, async (granted, error) =>
{
Console.WriteLine(granted);
await Task.Delay(500);
});
}
else
{
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
public void UnRegisterForPushNotifications()
{
}
public static Task RequestPermissions()
=> RequestPermissionsAsync();
public static async Task<bool> RequestPermissionsAsync()
{
try
{
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0) == false)
return true;
UNNotificationSettings settings = await UNUserNotificationCenter.Current.GetNotificationSettingsAsync().ConfigureAwait(false);
if (settings.AlertSetting == UNNotificationSetting.Enabled)
return true;
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
var (alertsAllowed, error) = await UNUserNotificationCenter.Current.RequestAuthorizationAsync(authOptions).ConfigureAwait(false);
return alertsAllowed;
}
catch (Exception ex)
{
Console.WriteLine("Error in RequestPermissionsAsync: " + ex.Message);
return false;
}
}
private UNMutableNotificationContent BuildStandardNotificationContent(NotificationRequest notificationRequest)
{
UNMutableNotificationContent content = new UNMutableNotificationContent();
content.Title = notificationRequest.Title;
content.Body = notificationRequest.Description;
IosOptions iOSOptions = notificationRequest.iOS;
if (!string.IsNullOrEmpty(iOSOptions.Sound))
content.Sound = UNNotificationSound.GetSound(iOSOptions.Sound);
if (notificationRequest.iOS.BadgeNumber.HasValue)
content.Badge = new NSNumber(iOSOptions.BadgeNumber.Value);
content.Sound ??= UNNotificationSound.Default;
content.UserInfo = BuildUserDictionary(notificationRequest);
return content;
}
private NSDictionary BuildUserDictionary(NotificationRequest notificationRequest)
{
string notificationRequestJson = notificationRequest.ToJson();
NSMutableDictionary userDictionary = new NSMutableDictionary
{
{ NOTIFICATION_ID, new NSNumber(notificationRequest.NotificationId) },
{ TITLE, new NSString(notificationRequest.Title) },
{ PRESENT_ALERT, new NSNumber(notificationRequest.iOS.PresentAlert) },
{ PLAY_SOUND, new NSNumber(notificationRequest.iOS.PlaySound) },
{ SHOW_BADGE, new NSNumber(notificationRequest.iOS.ShowBadge) },
{ PAYLOAD, new NSString(notificationRequest.Payload) },
{ NOTIFICATION_REQUEST, new NSString(notificationRequestJson) },
{ NOTIFICATION_ISLOCAL, new NSNumber(1) }
};
return userDictionary;
}
public async Task ShowAsync(int notificationId, string title, string description, string payload, AndroidOptions androidOptions = null, IosOptions iOSOptions = null)
{
UNCalendarNotificationTrigger trigger = null;
try
{
if (!await RequestPermissionsAsync().ConfigureAwait(false))
return;
iOSOptions ??= new IosOptions();
NotificationRequest notificationRequest = GetNotificationRequest(notificationId, title, description, payload, iOSOptions);
UNMutableNotificationContent content = BuildStandardNotificationContent(notificationRequest);
NSDateComponents notifyTime = GetNsDateComponentsFromDateTime(notificationRequest.NotifyTime);
trigger = UNCalendarNotificationTrigger.CreateTrigger(notifyTime, false);
await AddNotificationRequestAsync(notificationId.ToString(), content, trigger).ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine("Error in Show: " + ex.Message);
}
finally
{
trigger?.Dispose();
}
}
public async Task ShowHourlyAsync(int notificationId, string title, string description, Time time, string payload, AndroidOptions androidOptions = null, IosOptions iOSOptions = null)
{
await RepeatAsync(notificationId, title, description, Day.None, time, NotificationRepeat.Hourly, payload, iOSOptions).ConfigureAwait(false);
}
public async Task ShowDailyAsync(int notificationId, string title, string description, Time time, string payload, AndroidOptions androidOptions = null, IosOptions iOSOptions = null)
{
await RepeatAsync(notificationId, title, description, Day.None, time, NotificationRepeat.Daily, payload, iOSOptions).ConfigureAwait(false);
}
public async Task ShowWeeklyAsync(int notificationId, string title, string description, Day weekDay, Time time, string payload, AndroidOptions androidOptions = null, IosOptions iOSOptions = null)
{
await RepeatAsync(notificationId, title, description, weekDay, time, NotificationRepeat.Weekly, payload, iOSOptions).ConfigureAwait(false);
}
public async Task ScheduleAsync(int notificationId, string title, string description, DateTime dateTime, string payload, AndroidOptions androidOptions = null, IosOptions iOSOptions = null)
{
UNCalendarNotificationTrigger trigger = null;
try
{
if (!await RequestPermissionsAsync().ConfigureAwait(false))
return;
if (iOSOptions == null)
iOSOptions = new IosOptions();
//To Epoch timestamp
var notifyTimeSinceEpoch = dateTime.GetMilliSecondsSinceEpoch();
NotificationRequest notificationRequest = GetNotificationRequest(notificationId, title, description, payload, iOSOptions);
notificationRequest.NotifyTime = dateTime;
notificationRequest.NotifyTimeSinceEpoch = notifyTimeSinceEpoch;
UNMutableNotificationContent content = BuildStandardNotificationContent(notificationRequest);
NSDateComponents notifyTime = GetNsDateComponentsFromDateTime((DateTime?)dateTime);
trigger = UNCalendarNotificationTrigger.CreateTrigger(notifyTime, false);
await AddNotificationRequestAsync(notificationId.ToString(), content, trigger).ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine("Error in Schedule: " + ex.Message);
}
finally
{
trigger?.Dispose();
}
}
private async Task RepeatAsync(int notificationId, string title, string description, Day weekDay, Time time, NotificationRepeat repeatInterval, string payload, IosOptions iOSOptions)
{
UNCalendarNotificationTrigger trigger = null;
try
{
iOSOptions ??= new IosOptions();
NotificationRequest notificationRequest = new NotificationRequest()
{
NotificationId = notificationId,
Title = title,
Description = description,
CalledAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
RepeatInterval = repeatInterval,
WeekDay = weekDay,
Time = time,
Repeats = true,
Payload = payload,
iOS = iOSOptions,
Android = null
};
UNMutableNotificationContent content = BuildStandardNotificationContent(notificationRequest);
NSDateComponents notifyTime = GetNsDateComponents(notificationRequest.WeekDay, notificationRequest.Time);
trigger = UNCalendarNotificationTrigger.CreateTrigger(notifyTime, notificationRequest.Repeats);
//Console.WriteLine("NextTriggerDate : " + trigger.NextTriggerDate);
await AddNotificationRequestAsync(notificationId.ToString(), content, trigger);
}
catch (Exception ex)
{
Console.WriteLine("Error in Repeat[iOS]: " + ex.Message);
}
finally
{
trigger?.Dispose();
}
}
public async Task AddNotificationRequestAsync(string notificationId, UNNotificationContent notificationContent, UNCalendarNotificationTrigger trigger)
{
var notificationRequest = UNNotificationRequest.FromIdentifier(notificationId, notificationContent, trigger);
await UNUserNotificationCenter.Current.AddNotificationRequestAsync(notificationRequest).ConfigureAwait(false);
}
public async Task AddNotificationRequestAsync(string notificationId, UNNotificationContent notificationContent, UNTimeIntervalNotificationTrigger trigger)
{
var notificationRequest = UNNotificationRequest.FromIdentifier(notificationId, notificationContent, trigger);
await UNUserNotificationCenter.Current.AddNotificationRequestAsync(notificationRequest).ConfigureAwait(false);
}
public async Task CancelAsync(int notificationId)
{
try
{
await Task.Delay(1);
string[] itemList = new[]
{
notificationId.ToString(CultureInfo.CurrentCulture)
};
UNUserNotificationCenter.Current.RemovePendingNotificationRequests(itemList);
UNUserNotificationCenter.Current.RemoveDeliveredNotifications(itemList);
}
catch (Exception ex)
{
Console.WriteLine("Error in Cancel: " + ex.Message);
}
}
public async Task CancelAllAsync()
{
try
{
await Task.Delay(1);
UNUserNotificationCenter.Current.RemoveAllPendingNotificationRequests();
UNUserNotificationCenter.Current.RemoveAllDeliveredNotifications();
}
catch (Exception ex)
{
Console.WriteLine("Error in CancelAll: " + ex.Message);
}
}
public async Task<List<NotificationRequest>> GetPendingNotificationRequestsAsync()
{
await Task.Delay(1);
List<NotificationRequest> scheduledNotifications = new List<NotificationRequest>();
var notifications = await UNUserNotificationCenter.Current.GetPendingNotificationRequestsAsync();
//UILocalNotification[] notifications = UIApplication.SharedApplication.ScheduledLocalNotifications;
foreach (var notification in notifications)
{
if (notification != null)
{
var dictionary = GetParameters(notification.Content.UserInfo);
string notificationRequestJson = (string)dictionary[NOTIFICATION_REQUEST];
if (!string.IsNullOrEmpty(notificationRequestJson))
{
NotificationRequest notificationRequest = notificationRequestJson.JsonToObject<NotificationRequest>();
scheduledNotifications.Add(notificationRequest);
}
else
{
scheduledNotifications.Add(new NotificationRequest()
{
NotificationId = int.Parse((string)dictionary[NOTIFICATION_ID]),
Title = (string)dictionary[TITLE],
Description = notification.Content.Body,
Payload = (string)dictionary[PAYLOAD],
});
//scheduledNotifications.Add(new NotificationRequest()
//{
// NotificationId = int.Parse((string)dictionary[NOTIFICATION_ID]),
// Title = (string)dictionary[TITLE],
// Description = notification.Content.AlertBody,
// Payload = (string)dictionary[PAYLOAD],
//});
}
}
}
return scheduledNotifications;
}
#region Others
private static IDictionary<string, object> GetParameters(NSDictionary dictionary)
{
var parameters = new Dictionary<string, object>();
foreach (var data in dictionary)
parameters.Add($"{data.Key}", $"{data.Value}");
return parameters;
}
private NSDateComponents GetNsDateComponentsFromDateTime(DateTime? notifyTime)
{
var dateTime = notifyTime ?? DateTime.Now.AddSeconds(1);
return new NSDateComponents()
{
Day = dateTime.Day,
Hour = dateTime.Hour,
Minute = dateTime.Minute,
Second = dateTime.Second
};
}
private NSDateComponents GetNsDateComponents(Day weekDay, Time time)
{
var notifyTime = new NSDateComponents();
notifyTime.Hour = time.Hour;
notifyTime.Minute = time.Minute;
notifyTime.Second = time.Second;
if (weekDay != Day.None)
notifyTime.Weekday = (int)weekDay;
return notifyTime;
}
private NotificationRequest GetNotificationRequest(int notificationId, string title, string description, string payload, IosOptions iOSOptions)
{
return new NotificationRequest()
{
NotificationId = notificationId,
Title = title,
Description = description,
Payload = payload,
iOS = iOSOptions,
};
}
#endregion
}
}