Локальные уведомления — это оповещения, отправляемые приложениями, установленными на устройстве. Локальные уведомления часто используются для таких функций, как:
События календаря
Напоминания
Триггеры на основе расположения
Для каждой платформы требуется собственная реализация собственного кода для отправки и получения локальных уведомлений. Однако каждая реализация платформы может быть абстрагирована на кроссплатформенный уровень, чтобы обеспечить согласованный API для отправки и получения локальных уведомлений в приложении многоплатформенного пользовательского интерфейса приложений .NET (.NET MAUI).
Создание кроссплатформенной абстракции
Приложение .NET MAUI должно отправлять и получать локальные уведомления, не беспокоясь о реализации базовой платформы. Следующий INotificationManagerService интерфейс используется для определения кроссплатформенного API, который можно использовать для взаимодействия с локальными уведомлениями:
Это NotificationReceived событие позволяет приложению обрабатывать входящие уведомления.
Метод SendNotification отправляет уведомление при необходимости DateTime.
Метод ReceiveNotification обрабатывает уведомление при получении базовой платформой.
Интерфейс должен быть реализован на каждой платформе, которую требуется поддерживать локальные уведомления.
Реализация локальных уведомлений в Android
В Android локальное уведомление — это сообщение, отображаемое за пределами пользовательского интерфейса приложения для предоставления напоминаний или других сведений из приложения. Пользователи могут касаться уведомления, чтобы открыть приложение, или при необходимости выполнить действие непосредственно из уведомления. Сведения о локальных уведомлениях в Android см. в обзоре уведомлений по developer.android.com.
Чтобы приложение .NET MAUI отправляло и получало уведомления в Android, приложение должно предоставлять реализацию INotificationManagerService интерфейса.
Отправка и получение локальных уведомлений
В Android NotificationManagerService класс реализует INotificationManagerService интерфейс и содержит логику для отправки и получения локальных уведомлений:
C#
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using AndroidX.Core.App;
namespaceLocalNotificationsDemo.Platforms.Android;
publicclassNotificationManagerService : INotificationManagerService
{
conststring channelId = "default";
conststring channelName = "Default";
conststring channelDescription = "The default channel for notifications.";
publicconststring TitleKey = "title";
publicconststring MessageKey = "message";
bool channelInitialized = false;
int messageId = 0;
int pendingIntentId = 0;
NotificationManagerCompat compatManager;
publicevent EventHandler NotificationReceived;
publicstatic NotificationManagerService Instance { get; privateset; }
publicNotificationManagerService()
{
if (Instance == null)
{
CreateNotificationChannel();
compatManager = NotificationManagerCompat.From(Platform.AppContext);
Instance = this;
}
}
publicvoidSendNotification(string title, string message, DateTime? notifyTime = null)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}
if (notifyTime != null)
{
Intent intent = new Intent(Platform.AppContext, typeof(AlarmHandler));
intent.PutExtra(TitleKey, title);
intent.PutExtra(MessageKey, message);
intent.SetFlags(ActivityFlags.SingleTop | ActivityFlags.ClearTop);
var pendingIntentFlags = (Build.VERSION.SdkInt >= BuildVersionCodes.S)
? PendingIntentFlags.CancelCurrent | PendingIntentFlags.Immutable
: PendingIntentFlags.CancelCurrent;
PendingIntent pendingIntent = PendingIntent.GetBroadcast(Platform.AppContext, pendingIntentId++, intent, pendingIntentFlags);
long triggerTime = GetNotifyTime(notifyTime.Value);
AlarmManager alarmManager = Platform.AppContext.GetSystemService(Context.AlarmService) as AlarmManager;
alarmManager.Set(AlarmType.RtcWakeup, triggerTime, pendingIntent);
}
else
{
Show(title, message);
}
}
publicvoidReceiveNotification(string title, string message)
{
var args = new NotificationEventArgs()
{
Title = title,
Message = message,
};
NotificationReceived?.Invoke(null, args);
}
publicvoidShow(string title, string message)
{
Intent intent = new Intent(Platform.AppContext, typeof(MainActivity));
intent.PutExtra(TitleKey, title);
intent.PutExtra(MessageKey, message);
intent.SetFlags(ActivityFlags.SingleTop | ActivityFlags.ClearTop);
var pendingIntentFlags = (Build.VERSION.SdkInt >= BuildVersionCodes.S)
? PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable
: PendingIntentFlags.UpdateCurrent;
PendingIntent pendingIntent = PendingIntent.GetActivity(Platform.AppContext, pendingIntentId++, intent, pendingIntentFlags);
NotificationCompat.Builder builder = new NotificationCompat.Builder(Platform.AppContext, channelId)
.SetContentIntent(pendingIntent)
.SetContentTitle(title)
.SetContentText(message)
.SetLargeIcon(BitmapFactory.DecodeResource(Platform.AppContext.Resources, Resource.Drawable.dotnet_logo))
.SetSmallIcon(Resource.Drawable.message_small);
Notification notification = builder.Build();
compatManager.Notify(messageId++, notification);
}
voidCreateNotificationChannel()
{
// Create the notification channel, but only on API 26+.if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channelNameJava = new Java.Lang.String(channelName);
var channel = new NotificationChannel(channelId, channelNameJava, NotificationImportance.Default)
{
Description = channelDescription
};
// Register the channel
NotificationManager manager = (NotificationManager)Platform.AppContext.GetSystemService(Context.NotificationService);
manager.CreateNotificationChannel(channel);
channelInitialized = true;
}
}
longGetNotifyTime(DateTime notifyTime)
{
DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(notifyTime);
double epochDiff = (new DateTime(1970, 1, 1) - DateTime.MinValue).TotalSeconds;
long utcAlarmTime = utcTime.AddSeconds(-epochDiff).Ticks / 10000;
return utcAlarmTime; // milliseconds
}
}
Класс NotificationManagerService должен быть помещен в папку Android платформ > приложения. Кроме того, можно выполнять многонацелие на основе собственных критериев имени файла и папки, а не с помощью папки Android Платформы>. Дополнительные сведения см. в разделе "Настройка многонацеливания".
Android позволяет приложениям определять несколько каналов уведомлений. Конструктор NotificationManagerService создает базовый канал, используемый для отправки уведомлений. Метод SendNotification определяет логику конкретной платформы, необходимую для создания и отправки уведомления. Метод ReceiveNotification вызывается ОС Android при получении сообщения и вызывает NotificationReceived обработчик событий. Дополнительные сведения см. в статье "Создание уведомления по developer.android.com".
Метод SendNotification позволяет создать локальное уведомление сразу или в определенное время (DateTime). Можно запланировать отправку уведомления на определенное время (DateTime) с помощью класса AlarmManager. Это уведомление получит объект, производный от класса BroadcastReceiver.
По умолчанию уведомления, запланированные с помощью AlarmManager класса, не будут перезагружать устройство. Однако вы можете создать приложение для автоматического перепланированного уведомления, если устройство перезапущено. Дополнительные сведения см. в разделе Start an alarm when the device restarts (Запуск службы сигнализации при перезагрузке устройства) статьи Schedule repeating alarms (Планирование повторяющихся сигналов) на сайте developer.android.com. Сведения о фоновой обработке в Android см. в разделе Guide to Background processing (Руководство по фоновой обработке) на сайте developer.android.com.
Обработка входящих уведомлений
Приложение Android должно обнаруживать входящие уведомления и уведомлять NotificationManagerService экземпляр. Одним из способов достижения этого является изменение MainActivity класса.
Атрибут Activity в классе MainActivity должен указывать значение LaunchMode для LaunchMode.SingleTop:
Режим SingleTop предотвращает запуск нескольких экземпляров Activity , пока приложение находится на переднем плане. Это LaunchMode может быть не подходит для приложений, которые запускают несколько действий в более сложных сценариях уведомлений. Дополнительные сведения о значениях перечисления см. в LaunchMode разделе "Запуск действия Android" на developer.android.com.
Класс MainActivity также необходимо изменить для получения входящих уведомлений:
Метод CreateNotificationFromIntent извлекает данные уведомления из аргумента intent и передает его ReceiveNotification методу NotificationManagerService в классе. Метод CreateNotificationFromIntent вызывается как из метода OnCreate, так и с помощью метода OnNewIntent:
Когда приложение запускается с помощью данных уведомлений, Intent данные будут переданы методу OnCreate .
Если приложение уже находится на переднем плане, Intent данные будут переданы методу OnNewIntent .
Проверка разрешения
Для Android 13 (API 33) и более поздних версий требуется разрешение на отправку POST_NOTIFICATIONS уведомлений из приложения. Это разрешение должно быть объявлено в файле AndroidManifest.xml :
Реализация локальных уведомлений в iOS и Mac Catalyst
На платформах Apple локальное уведомление — это сообщение, которое передает важную информацию пользователям. Система обрабатывает доставку уведомлений на основе указанного времени или расположения. Сведения о локальных уведомлениях на платформах Apple см. в статье "Планирование уведомления локально из приложения на developer.apple.com".
Чтобы приложение .NET MAUI отправляло и получало уведомления на платформах Apple, приложение должно предоставлять реализацию INotificationManagerService интерфейса.
Отправка и получение локальных уведомлений
На NotificationManagerService платформах Apple класс реализует INotificationManagerService интерфейс и содержит логику для отправки и получения локальных уведомлений:
C#
using Foundation;
using UserNotifications;
namespaceLocalNotificationsDemo.Platforms.iOS;
publicclassNotificationManagerService : INotificationManagerService
{
int messageId = 0;
bool hasNotificationsPermission;
publicevent EventHandler? NotificationReceived;
publicNotificationManagerService()
{
// Create a UNUserNotificationCenterDelegate to handle incoming messages.
UNUserNotificationCenter.Current.Delegate = new NotificationReceiver();
// Request permission to use local notifications.
UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
{
hasNotificationsPermission = approved;
});
}
publicvoidSendNotification(string title, string message, DateTime? notifyTime = null)
{
// App doesn't have permissions.if (!hasNotificationsPermission)
return;
messageId++;
var content = new UNMutableNotificationContent()
{
Title = title,
Subtitle = "",
Body = message,
Badge = 1
};
UNNotificationTrigger trigger;
if (notifyTime != null)
// Create a calendar-based trigger.
trigger = UNCalendarNotificationTrigger.CreateTrigger(GetNSDateComponents(notifyTime.Value), false);
else// Create a time-based trigger, interval is in seconds and must be greater than 0.
trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.25, false);
var request = UNNotificationRequest.FromIdentifier(messageId.ToString(), content, trigger);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
{
if (err != null)
thrownew Exception($"Failed to schedule notification: {err}");
});
}
publicvoidReceiveNotification(string title, string message)
{
var args = new NotificationEventArgs()
{
Title = title,
Message = message
};
NotificationReceived?.Invoke(null, args);
}
NSDateComponents GetNSDateComponents(DateTime dateTime)
{
returnnew NSDateComponents
{
Month = dateTime.Month,
Day = dateTime.Day,
Year = dateTime.Year,
Hour = dateTime.Hour,
Minute = dateTime.Minute,
Second = dateTime.Second
};
}
}
Класс NotificationManagerService должен быть помещен в папку "Платформы > iOS " или "Платформы > Mac Catalyst ". Кроме того, можно выполнять многонацелие на основе собственных критериев имени файла и папки, а не с помощью папок Платформ . Дополнительные сведения см. в разделе "Настройка многонацеливания".
На платформах Apple необходимо запросить разрешение на использование уведомлений перед попыткой запланировать уведомление. Это происходит в конструкторе NotificationManagerService . Дополнительные сведения о разрешении локального уведомления см. в статье "Запрос разрешения на использование уведомлений на developer.apple.com".
Метод SendNotification определяет логику, необходимую для создания и отправки уведомления, и создает немедленное локальное уведомление с помощью UNTimeIntervalNotificationTrigger объекта или точного DateTime использования UNCalendarNotificationTrigger объекта. Метод ReceiveNotification вызывается iOS при получении сообщения и вызывает NotificationReceived обработчик событий.
Обработка входящих уведомлений
Для обработки входящих сообщений на платформах Apple необходимо создать делегат, который подклассы UNUserNotificationCenterDelegate:
C#
using UserNotifications;
namespaceLocalNotificationsDemo.Platforms.iOS;
publicclassNotificationReceiver : UNUserNotificationCenterDelegate
{
// Called if app is in the foreground.publicoverridevoidWillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
ProcessNotification(notification);
var presentationOptions = (OperatingSystem.IsIOSVersionAtLeast(14))
? UNNotificationPresentationOptions.Banner
: UNNotificationPresentationOptions.Alert;
completionHandler(presentationOptions);
}
// Called if app is in the background, or killed state.publicoverridevoidDidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
if (response.IsDefaultAction)
ProcessNotification(response.Notification);
completionHandler();
}
voidProcessNotification(UNNotification notification)
{
string title = notification.Request.Content.Title;
string message = notification.Request.Content.Body;
var service = IPlatformApplication.Current?.Services.GetService<INotificationManagerService>();
service?.ReceiveNotification(title, message);
}
}
Класс NotificationReceiver регистрируется в качестве UNUserNotificationCenter делегата в конструкторе NotificationManagerService и предоставляет входящие данные уведомления методу ReceiveNotificationNotificationManagerService в классе.
Реализация локальных уведомлений в Windows
Локальные уведомления в пакете SDK для приложений Windows — это сообщения, которые приложение может отправлять пользователю, пока они не находятся в вашем приложении. Содержимое уведомления отображается в временном окне в правом нижнем углу экрана и в Центре уведомлений. Локальные уведомления можно использовать для информирования пользователя о состоянии приложения или запроса пользователя на принятие действия.
Сведения о локальных уведомлениях в Windows, включая сведения о реализации упакованных и распакованных приложений, см. в обзоре уведомлений о приложениях.
Регистрация реализаций платформы
Каждая NotificationManagerService реализация должна быть зарегистрирована в интерфейсе INotificationManagerService , чтобы операции, предоставляемые интерфейсом, можно вызывать из кроссплатформенного кода. Это можно сделать, регистрируя типы со Services свойством MauiAppBuilder объекта в методе CreateMauiAppMauiProgram в классе:
Дополнительные сведения о внедрении зависимостей в .NET MAUI см. в разделе "Внедрение зависимостей".
Отправка и получение локальных уведомлений
Реализация INotificationManagerService может быть разрешена с помощью автоматического разрешения зависимостей или путем явного разрешения зависимостей. В следующем примере показано использование явного INotificationManagerService разрешения зависимостей для разрешения реализации:
C#
// Assume the app uses a single window.
INotificationManagerService notificationManager =
Application.Current?.Windows[0].Page?.Handler?.MauiContext?.Services.GetService<INotificationManagerService>();
Дополнительные сведения о разрешении зарегистрированных типов см. в разделе "Разрешение".
INotificationManagerService После разрешения реализации его операции можно вызвать:
C#
// Send
notificationManager.SendNotification();
// Scheduled send
notificationManager.SendNotification("Notification title goes here", "Notification messages goes here.", DateTime.Now.AddSeconds(10));
// Receive
notificationManager.NotificationReceived += (sender, eventArgs) =>
{
var eventData = (NotificationEventArgs)eventArgs;
MainThread.BeginInvokeOnMainThread(() =>
{
// Take required action in the app once the notification has been received.
});
};
}
Обработчик NotificationReceived событий приводит аргументы события к NotificationEventArgsаргументам, определяющим Title и Message свойствам:
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Отзыв о .NET MAUI
.NET MAUI — это проект с открытым исходным кодом. Выберите ссылку, чтобы оставить отзыв:
Присоединитесь к серии встреч для создания масштабируемых решений искусственного интеллекта на основе реальных вариантов использования с другими разработчиками и экспертами.