0
点赞
收藏
分享

微信扫一扫

iOS 通信通知 Communication Notifications 的实现

背景

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

方案

Communication Notifications (通讯通知)

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

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

通讯通知 Communication Notifications 具体实现

要使用通讯通知,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、通过使用 INPerson 和 INSendMessageIntent 创建对话信息将其添加到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);
    }
}
效果

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

举报

相关推荐

0 条评论