iOS 通信通知 Communication Notifications 的实现

4 篇文章 0 订阅

背景

在这里插入图片描述
看到群里有同学在咨询,推送通知如何自定义左侧的icon 部位,因为iOS 10之后有推出,通知扩展,所以大家知道可以通过Notification Extension 可以给通知添加媒体资源即图片、音视频等。但是我们也知道,通过通知扩展添加的图片是展示在右侧的,如下图:
在这里插入图片描述
那么如何修改左侧的icon,实现苹果短信的效果呢?带着疑问我们向下看。

方案

Communication Notifications (通讯通知)

查找苹果 官方文档WWDC 2021 发现,iOS 15之后,苹果推出了一个叫通讯通知的功能。可以看看苹果官方给的定义。

Apple has added the ability to distinguish your app’s notifications as communication notifications. These notifications will now feature the image or avatar of the contact they were sent from and can integrate with SiriKit so that Siri can intelligently provide shortcuts and suggestions for communication actions based on common contacts. For example, when users are setting allowed contacts for a Focus mode or are placing a call from your app. Siri will intelligently suggest contacts based on the intent data donated by your application.

Apple 添加了将应用程序的通知区分为通信通知的功能。这些通知现在将包含发送它们的联系人的图像或头像,并且可以与 SiriKit 集成,以便 Siri 可以智能地根据常用联系人为通信操作提供快捷方式和建议。例如,当用户为 Focus 模式设置允许的联系人或从您的应用程序拨打电话时。Siri 将根据您的应用程序提供的意图数据智能地建议联系人。

就是说,苹果提供了将推送通知区分为通信通知的功能,用通信通知可以显示用户的头像等内容。
图例:
在这里插入图片描述
看完定义与效果,我们发现这正是我们需要的功能,那么具体如何实现呢?

通讯通知 Communication Notifications 具体实现

To use communication notifications, apps will need to add the Communication Notifications capability to their App in Xcode and update the content of their notification in the app’s Notification Service Extension with an intent object that implements the new UNNotificationContentProviding protocol.

要使用通讯通知,APP 需要在 Xcode 中将通讯通知功能添加到其 APP,并在应用程序通知服务扩展中实现 UNNotificationContentProviding 协议。

1、 首先将以下键值添加到APP Info.plist 文件中
<key>NSUserActivityTypes</key>
   <array>
   	<string>INStartCallIntent</string>
   	<string>INSendMessageIntent</string>
   </array>

在这里插入图片描述

2、在Xcode - Signing & Capabilities 中添加 Communication Notifications 功能

在这里插入图片描述

本地通知 - 实现通讯通知
1、首先导入以下头文件
#import <Intents/Intents.h>
#import <UserNotifications/UserNotifications.h>
2、通过使用 INPersonINSendMessageIntent 创建对话信息将其添加到APP的推送通知消息中。
//创建一个名字
NSPersonNameComponents *nameComponents = [[NSPersonNameComponents alloc] init];
nameComponents.nickname = message.fromUsername;// 用户名
//创建参与SiriKit交互的用户消息发送者   
INPerson *messageSender = [[INPerson alloc]initWithPersonHandle:[[INPersonHandle alloc]initWithValue:nil type:INPersonHandleTypeUnknown] nameComponents:nameComponents displayName:message.fromName image:avatarImage contactIdentifier:nil customIdentifier:message.fromUsername isMe:NO suggestionType:(INPersonSuggestionTypeNone)];
//创建发送消息请求    
INSendMessageIntent *intent = [[INSendMessageIntent alloc] initWithRecipients:@[messageSender] outgoingMessageType:(INOutgoingMessageTypeOutgoingMessageText) content:contentAttribut.string speakableGroupName:[[INSpeakableString alloc]initWithSpokenPhrase:@""] conversationIdentifier:message.msgId serviceName:nil sender:messageSender attachments:nil];
    
[intent setImage:avatarImage forParameterNamed:@"speakableGroupName"];

//创建SiriKit 交互对象    
INInteraction *interaction = [[INInteraction alloc]initWithIntent:intent response:nil];
interaction.direction = INInteractionDirectionIncoming;
[interaction donateInteractionWithCompletion:nil];

完整实现代码如下:

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = message.fromName;
        content.body = contentAttribut.string;
        content.sound = [UNNotificationSound defaultSound];
        content.badge = @([UIApplication sharedApplication].applicationIconBadgeNumber + 1);
        content.userInfo = @{
            @"url":@"xxxxxxx",
        };
        if (@available(iOS 15.0, *)) {
            //实现私信消息内容展示
            if (message.fromUsername && message.fromAvatar && message.fromName && message.msgId)
            {
                //需要先将图片下载下来,我们这里使用的SDWebImageDownloader下载图片
                NSURL *imageURL = [NSURL URLWithString:message.fromAvatar];
                __block INImage *avatarImage = nil;
                
                [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:imageURL completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
                    if (image) {
                        avatarImage = [INImage imageWithImageData:data];
                    }
                    // 消息发送方
                    NSPersonNameComponents *nameComponents = [[NSPersonNameComponents alloc] init];
                    nameComponents.nickname = message.fromUsername;// 用户名

                    INPerson *messageSender = [[INPerson alloc]initWithPersonHandle:[[INPersonHandle alloc]initWithValue:nil type:INPersonHandleTypeUnknown] nameComponents:nameComponents displayName:message.fromName image:avatarImage contactIdentifier:nil customIdentifier:message.fromUsername isMe:NO suggestionType:(INPersonSuggestionTypeNone)];

                    INSendMessageIntent *intent = [[INSendMessageIntent alloc] initWithRecipients:@[messageSender] outgoingMessageType:(INOutgoingMessageTypeOutgoingMessageText) content:contentAttribut.string speakableGroupName:[[INSpeakableString alloc]initWithSpokenPhrase:@""] conversationIdentifier:message.msgId serviceName:nil sender:messageSender attachments:nil];
                    [intent setImage:avatarImage forParameterNamed:@"speakableGroupName"];

                    INInteraction *interaction = [[INInteraction alloc]initWithIntent:intent response:nil];
                    interaction.direction = INInteractionDirectionIncoming;
                    [interaction donateInteractionWithCompletion:nil];

                    
                    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:message.msgId content:[content contentByUpdatingWithProvider:intent error:nil] trigger:nil];
                    
                    [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
                        NSLog(@"成功添加推送");
                    }];
                }];
            }else{
                UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:message.msgId content:content trigger:nil];
                [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
                    NSLog(@"成功添加推送");
                }];
            }
        }else{
            UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:message.msgId content:content trigger:nil];
            [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
                NSLog(@"成功添加推送");
            }];
        }
远程通知 - 实现通讯通知
1、首先添加通知扩展(Notification Service Extension

iOS10 之后的通知具有扩展功能,可以在系统收到通知、展示通知时做一些事情。
在这里插入图片描述

2、将以下键值对添加到通知扩展中
<key>NSUserActivityTypes</key>
   <array>
   	<string>INStartCallIntent</string>
   	<string>INSendMessageIntent</string>
   </array>

在这里插入图片描述

3、在通知扩展下 NotificationService 中的以下方法中,实现通讯通知,具体实现方式与本地推送大同小异。
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
}

核心代码如下:

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    
    self.bestAttemptContent = [request.content mutableCopy];
    
    if (@available(iOS 15.0, *)) {
        //实现消息内容展示
        // 发送者名称
        NSString *fromUsername = self.bestAttemptContent.userInfo[@"xxx"];
        // 发送者头像url地址
        NSString *fromAvatar = self.bestAttemptContent.userInfo[@"xxx"];
        // 发送者昵称
        NSString *fromNickName = self.bestAttemptContent.userInfo[@"xxx"];
        // 消息 id
        NSString *messageId = self.bestAttemptContent.userInfo[@"xxx"];
        if (fromUsername && fromAvatar && fromNickName && messageId)
        {
            //需要先下载图片
            NSURL *imageURL = [NSURL URLWithString:fromAvatar];
            __block INImage *avatarImage = nil;
            
            [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:imageURL completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
                if (image) {
                    avatarImage = [INImage imageWithImageData:data];
                }
                // 消息发送方
                NSPersonNameComponents *nameComponents = [[NSPersonNameComponents alloc] init];
                nameComponents.nickname = fromUsername;// 用户名
                
                INPerson *messageSender = [[INPerson alloc]initWithPersonHandle:[[INPersonHandle alloc]initWithValue:nil type:INPersonHandleTypeUnknown] nameComponents:nameComponents displayName:fromNickName image:avatarImage contactIdentifier:nil customIdentifier:fromUsername isMe:NO suggestionType:(INPersonSuggestionTypeNone)];
                
                INSendMessageIntent *intent = [[INSendMessageIntent alloc] initWithRecipients:@[messageSender] outgoingMessageType:(INOutgoingMessageTypeOutgoingMessageText) content:self.bestAttemptContent.body speakableGroupName:[[INSpeakableString alloc]initWithSpokenPhrase:@""] conversationIdentifier:messageId serviceName:nil sender:messageSender attachments:nil];
                [intent setImage:avatarImage forParameterNamed:@"speakableGroupName"];
                
                INInteraction *interaction = [[INInteraction alloc]initWithIntent:intent response:nil];
                interaction.direction = INInteractionDirectionIncoming;
                [interaction donateInteractionWithCompletion:nil];
                
                self.bestAttemptContent =  [[request.content contentByUpdatingWithProvider:intent error:nil] mutableCopy];
            }];
            
        }else{
            contentHandler(self.bestAttemptContent);
        }
    }else{
        contentHandler(self.bestAttemptContent);
    }
}
效果

至此,通讯通知功能完成,可以测试了。我们实现后的效果如下图:
在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Websocket是一种 HTML5的协议,它允许在客户端和服务器之间建立持久的连接。这个连接是双向的,因此可以通过它来实现实时的通讯。Websocket协议是一种基于事件的协议,其中,服务器可以向客户端发送消息,而客户端接收到消息之后,可以进行相应的操作。 在实现通知功能时,Websocket是一种非常方便的技术。一般来说,我们可以使用Websocket建立一个持久的连接,并将这个连接保存在服务器端。当有需要发送通知的时候,服务器端可以通过这个连接将消息发送给客户端,客户端接收到消息之后,可以通过事件处理程序来处理收到的消息。 Websocket通知功能的实现有两种基本的方式:一种是客户端主动请求服务器查看是否有新的消息,另一种是服务器主动向客户端发送消息,推送新的通知。 1. 客户端主动请求方式: 在这种方式中,客户端定期向服务器发送请求,询问是否有新的通知。服务器在接收到请求之后查看是否有新的通知,如果有,就将通知信息返回给客户端,否则返回空信息。 客户端的实现: ``` // 建立Websocket连接 var ws = new WebSocket("ws://localhost:8080/"); // 每隔1秒向服务器请求是否有新的通知 setInterval(function() { ws.send("getNewNotification"); }, 1000); // 处理服务器返回的消息 ws.onmessage = function(event) { var message = event.data; if(message == "") { // 没有新的通知 } else { // 处理返回的通知信息 } } ``` 服务器端的实现: ``` // 建立Websocket服务 var server = new WebSocketServer({port: 8080}); // 当客户端连接时,记录连接 server.on('connection', function(ws) { console.log("connected"); // 处理客户端发送来的请求 ws.on('message', function(message) { if(message == "getNewNotification") { // 如果有新的通知,将通知信息发送到客户端 ws.send("newNotification"); } else { // 其他情况 } }); }); ``` 2. 服务器向客户端推送方式: 在这种方式中,服务器维护一个通知列表,当有新的通知产生时,就将通知信息发送给客户端。 客户端的实现: ``` // 建立Websocket连接 var ws = new WebSocket("ws://localhost:8080/"); // 处理服务器返回的消息 ws.onmessage = function(event) { var message = event.data; if(message == "") { // 没有新的通知 } else { // 处理返回的通知信息 } } ``` 服务器端的实现: ``` // 建立Websocket服务 var server = new WebSocketServer({port: 8080}); // 通知列表(存储一个通知数组) var notifications = []; // 将新的通知加入列表并发送给客户端 function sendNewNotification(notification) { notifications.push(notification); server.clients.forEach(function(client) { client.send(notification); }); } // 模拟新的通知产生(实际中通知可以通过其他方式产生) setInterval(function() { sendNewNotification("newNotification"); }, 1000); // 当客户端连接时,记录连接 server.on('connection', function(ws) { console.log("connected"); // 将通知列表发送给客户端 notifications.forEach(function(notification) { ws.send(notification); }); }); ``` 以上是使用Websocket实现通知功能的基本思路和代码示例。在实际应用中,我们还需要考虑如何确保通知的可靠性和安全性,如何避免通知消息漏掉等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

假装自己很用心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值