ABP文档 - 通知系统

作者:信息科学

各位老师:

二、通知应用

{    "userId": 2,    "state": 0,    "notification": {        "notificationName": "System.LowDisk",        "data": {            "message": {                "sourceName": "MyLocalizationSourceName",                "name": "LowDiskWarningMessage"            },            "type": "Abp.Notifications.LocalizableMessageNotificationData",            "properties": {                "remainingDiskInMb": "42"            }        },        "entityType": null,        "entityTypeName": null,        "entityId": null,        "severity": 0,        "creationTime": "2016-02-09T17:03:32.13",        "id": "0263d581-3d8a-476b-8e16-4f6a6f10a632"    },    "id": "4a546baf-bf17-4924-b993-32e420a8d468"}

学校下发通知“关于认真做好2012年山东大学优秀教师、先进教育工作者评选推荐工作的通知”,详情请见:

至此,iOS 10本地通知已经解析完毕,下一篇是远程通知,......

实例项目

参考资料

通知定义

iOS 9 - Text Input action

基于 HTTP/2 的推送请求 UIUserNotificationActionBehavior,全新的 Provider API 等

abp.event.on('abp.notifications.received', function (userNotification) {    abp.notifications.showUiNotifyForUserNotification(userNotification);});

iOS 10以前的通知比较杂乱,把本地通知和远程通知分开了,诞生了许多功能类似的API,很容易让初学者犯迷糊。而iOS 10的通知把API做了统一,利用独立的UserNotifications.framework框架来管理通知;并且,还增加了撤销单条通知、更新已展示通知、中途修改通知内容等等,以及在通知中展示图片视频,自定义通知UI等一系列新功能;总之,iOS 10的通知功能十分强大。

在定义好这个通知供应器后,我们应该在模块的PreInitialize事件里注册它,如下所示:

一、发展历程:

发布通知

触发机制

    // 如果repeats为YES,那么triggerWithTimeInterval的值要大于60s
    UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:3 repeats:NO];

    NSString *requestIdentifier = @"requestIdentifier";

    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier content:content trigger:trigger1];

UNTimeIntervalNotificationTrigger

设置通知触发的条件,分为以下几类:

  • 1.UNPushNotificaitonTrigger

推送服务的Trigger,由系统创建

  • 2.UNTimeIntervalNotificaitonTrigger

时间触发器,可以设置多长时间后触发通知,repeats参数为是否重复触发,如果设置YES,那么triggerWithTimeInterval的时间必须大于60s

  • 3.UNCalendarNotificaitonTrigger

日期触发器,可以设置特定日期触发

  • 4.UNLocationNotificaitonTrigger

位置触发器,用于到达特定位置后才触发通知,需要设置CLRegion的具体区域

发送模式

添加通知

    // 创建通知对象
    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init]];
    // 设置通知标题
    noticeContent.title = @"iOS10通知";
    // 设置通知子标题
    noticeContent.subtitle = @"新通知学习笔记";
    // 设置通知内容
    noticeContent.body = @"新通知变化很大,之前本地通知和远程推送是两个类,现在合成一个了。";
    // 添加通知的声音
    UNNotificationSound *sound = [UNNotificationSound soundNamed:@"caodi.m4a"];
    noticeContent.sound = sound;

UNMutableNotificationContent

通知的内容,可以设置通知的标题、副标题、具体内容,以及通知的图片、视频、声音和交互信息等等

UNNotificationSound

应用在后台时收到通知时的提示音

每一个通知类型都应当有一个唯一的名称(如示例中的SentFrendshipRequestCommentPhoto)。

扩展通知

我们可以在通知中添加声音、图片和视频,来丰富通知的内容,在支持3D-touch的手机上,重压之后会全面显示;另外,我们也可以添加交互式通知,进一步提高用户体验

图片 1

UNNotificationationAttachment

通知的附近,我们可以在附近中添加图片、音频或视频。

  • 简介
    • 发送模式
    • 通知类型
    • 通知数据
    • 通知重要性
    • 关于通知持久化
  • 订阅通知
  • 发布通知
  • 用户通知管理器
  • 实时通知
    • 客户端
  • 通知存储
  • 通知定义

iOS 5 - 加入通知中心页面

因此,showUiNotifyForUserNotification可以为你的数据类型创建显示的消息,如果你只是需要格式的消息,你可以直接使用abp.notifications.getFormattedMessageFromUserNotification

iOS 7 - 后台静默推送

application(_:didReceiveRemoteNotification:fetchCompletionHandle:)

有两种通知类型:

发送通知

    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
        NSLog(@"发送通知出错: %@", error);
    }];

addNotificationRequest:withCompletionHandler:

把通知添加到通知中心,就可以发送通知了

abp.event.on('abp.notifications.received', function (userNotification) {    console.log(userNotification);});

的通知之前,有必要了解一下通知的历史现状。由于通知可以方便的提示用户应用的状态、传递重要的信息,所以自从iOS 3引入通知以来,几乎每个新的版本,Apple都会增强通知的功能。

通知存储

申请权限

    // 获取通知中心对象
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

    // 申请通知权限
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (granted) {
            NSLog(@"通知开启");
        } else {
            NSLog(@"关闭通知");
        }
    }];

    // 获取授权的通知权限
    [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        NSLog(@"%@", settings);
    }];

requestAuthorizationWithOptions:

申请通知的权限,iOS 10不再区分远程通知和本地通知的权限申请,统一用该方法做权限申请

本节内容:

添加交互式通知

添加交互式通知

    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init];

    // 文字action
    UNTextInputNotificationAction *action1 = [UNTextInputNotificationAction actionWithIdentifier:@"replyAction" title:@"文字回复" options:UNNotificationActionOptionNone];
    // 进入应用action
    UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"enterAction" title:@"进入应用" options:UNNotificationActionOptionForeground];
    // 取消action
    UNNotificationAction *action3 = [UNNotificationAction actionWithIdentifier:@"cancelAction" title:@"取消" options:UNNotificationActionOptionDestructive];

    UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:@"Categroy" actions:@[action1, action2, action3] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];

    [[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:[NSSet setWithObject:category]];

    noticeContent.categoryIdentifier = @"Categroy";

获取交互动作

    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
{
    NSString *categoryIdentifier = response.notification.request.content.categoryIdentifier;

    if ([categoryIdentifier isEqualToString:@"Categroy"]) {
        if ([response.actionIdentifier isEqualToString:@"replyAction"]) {
            UNTextInputNotificationResponse *textResponse = (UNTextInputNotificationResponse*)response;

            NSString *userText = textResponse.userText;

            NSLog(@"您输入的内容:%@", userText);

        } else if ([response.actionIdentifier isEqualToString:@"enterAction"]) {
            NSLog(@"点击进入了应用");
        } else {
            NSLog(@"点击了取消");
        }
    }

    completionHandler();
}

iOS 10把接收通知的方法做了统一,不再区分接收本地和远程的通知,只分前台和后台时受到的通知。

接收通知的步骤:

1.设置通知的代理,一般设置在AppDelegate

[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];

2.实现代理方法

    // 应用在前台收到通知的处理方法
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler

    // 应用在后台收到通知的处理方法
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler

启动模板包含了当接收到一个推送信息后显示UI通知的代码。

iOS 6 - 通知中心页面与 iCloud 同步

最后,你可以在你应用中注入并使用INotificationDefinitionManager来获取通知定义,接着你可能想准备一个允许用户自己订阅这些通知的页面。

iOS 8 - 重新设计notification权限请求,加入交互式通知

Actionable 通知 registerUserNotificationSettings(_:),UIUserNotificationActionUIUserNotificationCategoryapplication(_:handleActionWithIdentifier:forRemoteNotification:completionHandler:)

通知用来告知用户系统里特定的事件发生了,ABP提供一个发布/订阅,它基于实时通知基础框架。

自定义通知样式

iOS 10可以设置通知的UI样式,更加方便给用户定制化。必须用iPhone7或iPhone7 Plus,iPhone6s及以下硬件,即使升级到iOS 10也无法显示自定义通知的样式

1.创建自定义通知UI文件,在XcodeFile->New->Targe会出现下面的视图

图片 2

其中,与通知相关的扩展有两个:Notification ContentNotification Service Extension,前者是自定义通知的类型,后者是我们收到远程通知后,在展示之前对通知的修改。所以,我们采用前者

2.修改通知视图的控制器,自定义通知样式

  • NotificationViewController文件:

- (void)didReceiveNotification:(UNNotification *)notification可以设置UI显示的数据

  • MainInterface.storyboard文件

我们可以通过这个storyboard来具体定制通知的样式

3.应用自定义通知样式

修改NotificationViewControllerinfo.plist文件

图片 3

  • UNNotificationExtensionCategory

UNNotificationCategory的标识,需要设置为我们的通知的标识

  • UNNotificationExtensionInitialContentSizeRatio

通知内容显示的比例大小,默认为1

  • UNNotificationExtensionDefaultContentHidden

是否隐藏默认通知,设置为YES后,默认通知会隐藏

这里还有一些其它参数,你可以在代码中检查它,一个通知的定义只有名称是必需的。

iOS 3 - 引入推送通知

UIApplication 的 registerForRemoteNotificationTypesUIApplicationDelegateapplication(_:didRegisterForRemoteNotificationsWithDeviceToken:)application(_:didReceiveRemoteNotification:)

通知数据

iOS 4 - 引入本地通知

scheduleLocalNotificationpresentLocalNotificationNow:application(_:didReceive:)

INotificationSubscriptionManager还有UnsubscribeAsync,IsSubscribedAsyncGetSubscriptionsAsyn等方法来管理订阅。

移除通知

[[UNUserNotificationCenter currentNotificationCenter] removePendingNotificationRequestsWithIdentifiers:@[@"requestIdentifier"]];

public class MyService : ITransientDependency{    private readonly INotificationPublisher _notiticationPublisher;    public MyService(INotificationPublisher notiticationPublisher)    {        _notiticationPublisher = notiticationPublisher;    }    //发送一个一般通知给一个特定用户    public async Task Publish_SentFrendshipRequest(string senderUserName, string friendshipMessage, UserIdentifier targetUserId)    {        await _notiticationPublisher.PublishAsync("SentFrendshipRequest", new SentFrendshipRequestNotificationData(senderUserName, friendshipMessage), userIds: new[] { targetUserId });    }    //发送一个实体通知给一个特定用户    public async Task Publish_CommentPhoto(string commenterUserName, string comment, Guid photoId, UserIdentifier photoOwnerUserId)    {        await _notiticationPublisher.PublishAsync("CommentPhoto", new CommentPhotoNotificationData(commenterUserName, comment), new EntityIdentifier(typeof, photoId), userIds: new[] { photoOwnerUserId });    }    //发送一个一般通知给所有当前租户里的订阅它的用户    public async Task Publish_LowDisk(int remainingDiskInMb)    {        //Example "LowDiskWarningMessage" content for English -> "Attention! Only {remainingDiskInMb} MBs left on the disk!"        var data = new LocalizableMessageNotificationData(new LocalizableString("LowDiskWarningMessage", "MyLocalizationSourceName"));        data["remainingDiskInMb"] = remainingDiskInMb;        await _notiticationPublisher.PublishAsync("System.LowDisk", data, severity: NotificationSeverity.Warn);       }}

添加图片

    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init];

    NSString *imageFile = [[NSBundle mainBundle] pathForResource:@"sport" ofType:@"png"];
    UNNotificationAttachment *imageAttachment = [UNNotificationAttachment attachmentWithIdentifier:@"imageAttachment" URL:[NSURL fileURLWithPath:imageFile] options:nil error:nil];
    NSAssert(imageAttachment != nil, @"imageAttach 不能为空");
    noticeContent.attachments = @[imageAttachment];

有两种方式可以发送通知给用户:

添加视频

    UNMutableNotificationContent *noticeContent = [[UNMutableNotificationContent alloc] init];

    NSString *movieFile = [[NSBundle mainBundle] pathForResource:@"movie" ofType:@"mp4"];
    UNNotificationAttachment *movieAttachment = [UNNotificationAttachment attachmentWithIdentifier:@"movieAttachment" URL:[NSURL fileURLWithPath:movieFile] options:nil error:nil];
    NSAssert(movieAttachment != nil, @"movieAttach 不能为空");
    noticeContent.attachments = @[movieAttachment];

你不需要在用前先定义一个通知,你只管使用任何通知名称而无需定义,但是,定义它可能给你带来额外的好处,例如,定义后你可以在你的应用里检查所有的通知。鉴于这种情况,我们可以为我们的模块定义一个通知供应器,如下所示:

INotificationSubscriptionManager提供了用来订阅通知的API,例如:

通知系统使用IRealTimeNotifier来发送实时通知给用户,这可以使用任何类型的实时通讯系统实现,我们可以用一个单独实现的SignalR包,启动模板已经安装了SignalR,查看SignalR集成文档获取更多信息。

通知重要性有5个级别,定义在NotificationSeverity枚举里:Info,Success,Warn,ErrorFatal,默认为Info

kid1412附:英文原文:

注意:如果我们发布一个通知给一个特定用户,那么这个用户不需要订阅这个通知。

实时通知

简介

“Abp.NewUserRegistered”是这个通知的唯一名称,我们定义了一个可本地化的displayName(当在UI上订阅这个通知时可以显示它),最后,我们声明这个通知只对拥有“App.Pages.UserManagerment”许可的用户可用。

abp.event.on('abp.notifications.received', function (userNotification) {    if (userNotification.notification.data.type === 'Abp.Notifications.LocalizableMessageNotificationData') {        var localizedText = abp.localization.localize(            userNotification.notification.data.message.name,            userNotification.notification.data.message.sourceName        );        $.each(userNotification.notification.data.properties, function (key, value) {            localizedText = localizedText.replace('{'   key   '}', value);        });        alert('New localized notification: '   localizedText);    } else if (userNotification.notification.data.type === 'Abp.Notifications.MessageNotificationData') {        alert('New simple notification: '   userNotification.notification.data.message);    }});

关于通知持久化

查看通知存储小节获取更多信息。

这显示一个UI通知,如下所示(上面描述的推送的System.LowDisk通知):

在第一个例子里, 我们发布一个通知给一个单独的用户,SentFrendshipRequestNotificationData应该继承于NotificationData,如下所示:

(userNotification), 它内部被showUiNotifyForUserNotification。

它可工作于内容的通知数据类型(LocalizableMessageNotificationData和MessageNotificationData),如果你是自定义的通知数据类型,那么你应该像下面这样注册数据格式:

首先,我们注入INotificationSubscriptionManager,第一方法订阅一个一般通知,当某人发送一个好友请求时,用户会收到通知,第二个订阅一个与特定实体相关的通知,当某人给特定照片写评论后,用户会收到通知。

当接收到一个实时的通知,ABP在客户端触发一个全局事件,你可以用如下的方式注册来得到通知:

[Serializable]public class SentFrendshipRequestNotificationData : NotificationData{    public string SenderUserName { get; set; }    public string FriendshipMessage { get; set; }    public SentFrendshipRequestNotificationData(string senderUserName, string friendshipMessage)    {        SenderUserName = senderUserName;        FriendshipMessage = friendshipMessage;    }}
  • userId:当前用户Id,通常你不需要这个因为你知道当前的户。
  • state:UserNotificationState的枚举值,0:Unread,1:Read。
  • notification:通知明细:
    • notificationName:这个通知的唯一名称(发布时也用这个名称)。
    • data:通知数据,在这个示例里,我们使用LocalizableMessageNotificationData(和之前发布的示例一致):
      • message:本地化的消息信息,我们可以用sourceName和name来本地化界面上的消息。
      • type:通知数据类型,全类型名,包含命名空间,当在处理通知数据时,我们可以检查这个类型。
      • properties:基于字典的自定义属性。
    • entityType、entityTypeName和entityId:实体信息(如果这是一个实体实时通知)
    • severity:一个NotificationSeverity枚举值,0:Info,1:Success,2:Warn,3:Error,4:Fatal。
    • id:通知Id。
  • id:用户通知Id。

第二个例子,我们发送一个通知给一个特定用户并传递一个特定实体,通知数据类不需要可序列化(因为默认使用JSON序列器),但建议把它标记为可序列化,因为你可能会在不同应用中移动而且你将来也可能想使用二进制可序列化器。当然如前面所述,通知数据是可选的,并不是所有的通知都需要它。

  • 用户订阅一个特定的通知类型,然后我们发布一个此类型的通知,它会分发给所有订阅的用户,这就是发布/订阅模式。
  • 我们可以直接发送一个通知给目标用户。
public class MyAppNotificationProvider : NotificationProvider{    public override void SetNotifications(INotificationDefinitionContext context)    {        context.Manager.Add(            new NotificationDefinition(                "App.NewUserRegistered",                displayName: new LocalizableString("NewUserRegisteredNotificationDefinition", "MyLocalizationSourceName"),                permissionDependency: new SimplePermissionDependency("App.Pages.UserManagement")                )            );    }}

INotificationPublisher用来发布通知,例如:

public class AbpZeroTemplateCoreModule : AbpModule{    public override void PreInitialize()    {        Configuration.Notifications.Providers.Add<MyAppNotificationProvider>();    }    //...}

订阅通知

通知数据是可选的,有些通知可能就不需要数据。ABP已经提供足以满足大部分情况的预定义通知数据类型,简单的信息可以用MessageNotificationData,本地化和可参数化的通知信息可以使用LocalizableMessageNotificationData,我们会在以后章节看到使用示例。

为了能处理通知数据,我们应当检查这个数据类型,这个例子简单的从通知数据里获取消息,如果是本地化的消息(LocalizableMessageNotificationData),我们本地化这个消息并替换参数, 如果是简单消息(MessageNotificationData),我们直接获取这个消息,当然,在真实的项目里,我们不会使用alert函数,我们可以使用abp.notifyapi来显示良好的UI通知。

图片 4

通知系统使用INotificationStore来持久化通知,该接口实现后才能使通知系统正常工作,你可以自己实现它或使用已经实现它的module-zero。

IUserNotificationManager用来管理用户的通知,它get,update或delete一个用户的通知,你可以用它为你的应用准备一个通知列表页面。

每接收到一个实时通知,都会触发abp.notifications.received事件事件,你可以像上面那样注册该事件来获取通知,查看javascript事件总线文档获取事件更多信息。一个收到的“System.LowDisk”通知的Json示例:

用户通知管理器

public class MyService : ITransientDependency{    private readonly INotificationSubscriptionManager _notificationSubscriptionManager;    public MyService(INotificationSubscriptionManager notificationSubscriptionManager)    {        _notificationSubscriptionManager = notificationSubscriptionManager;    }    //订阅一个一般通知    public async Task Subscribe_SentFrendshipRequest(int? tenantId, long userId)    {        await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), "SentFrendshipRequest");        }    //订阅一个实体通知    public async Task Subscribe_CommentPhoto(int? tenantId, long userId, Guid photoId)    {        await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), "CommentPhoto", new EntityIdentifier(typeof, photoId));       }}

通知重要性

虽然你可以用IUserNotificationManager来查询通知,但我们通常想推送一个实时通知到客户端。

当然,你不会只是日志这个通知,你可以使用通知数据把通知信息显示给用户,例如:

通知类型

注意:通知系统用一个后台作业异步调用IRealTimeNotifier,所以,通知可能会有一点点的延迟。

一个通知通常包含一个通知数据,例如:“如果一个用户发送一个好友请求,那么通知我”该通知可能有两个数据属性:发送者名字(谁发送了这个好友请求)和备注(发送者写在请求里的信息),很明显,通知数据类型与通知类型是紧密联系的,不同的通知类型有不同的数据类型。

如果你想实现上面这样的逻辑,有一个更容易且富有弹性的方式,当接收到一个推送的通知,你只需要一行代码来显示UI通知:

在这个对象里:

客户端

  • 一般通知:任意的通知类型,“如果一个用户发送一个好友请求,那么通知我”就是一个此类型的通知。
  • 实体通知:与一个特定的实体关联,“如果一个用户给这张图片发了评论,那么通知我”就是一个基于实体的通知,因为它与一个特定的photo实体关联,用户可能想为某些图片发出通知,而不是所有图片。
abp.notifications.messageFormatters['MyProject.MyNotificationDataType'] = function(userNotification) {    return ...; //此处格式化并返回消息};

第三个例子,我们没有定义一个专用的通知数据类,而是直接使用内容的LocalizableMessageNotificationData类,并使用基于字典的数据,并发布一个“Warn”通知,LocalizableMessageNotificationData可以存储基于字典的任意数据(如果自定义的通知数据类继承于NotificationData类,那么也可以这么用),我们使用“remainingDiskInMb”作为本地化参数,本地化信息可以包含这些参数(如示例中的“Attention!Only{remainingDiskInMb} MBs left on the disk!”),我们在客户端小节里可以看到如果本地化。

文档目录

本文由永利电玩城发布,转载请注明来源

关键词: 永利电玩城