背景

iOS 通信通知 Communication Notifications 的实现
看到群里有同学在咨询,推送告诉怎么自定义左边的icon 部位,由于iOS 10之后有推出,告诉扩展,所以咱们知道能够经过Notification Extension 能够给告诉增加媒体资源即图片、音视频等。但是咱们也知道,经过告诉扩展增加的图片是展现在右侧的,如下图:
iOS 通信通知 Communication Notifications 的实现
那么怎么修正左边的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 将依据您的应用程序供给的目的数据智能地主张联络人。

就是说,苹果供给了将推送告诉区分为通讯告诉的功用,用通讯告诉能够显现用户的头像等内容。 图例:

iOS 通信通知 Communication Notifications 的实现
看完定义与作用,咱们发现这正是咱们需求的功用,那么详细怎么完成呢?

通讯告诉 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>

iOS 通信通知 Communication Notifications 的实现

2、在XcodeSigning & Capabilities 中增加 Communication Notifications 功用

iOS 通信通知 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 之后的告诉具有扩展功用,能够在体系收到告诉、展现告诉时做一些事情。

iOS 通信通知 Communication Notifications 的实现

2、将以下键值对增加到告诉扩展中
<key>NSUserActivityTypes</key>
   <array>
   	<string>INStartCallIntent</string>
   	<string>INSendMessageIntent</string>
   </array>

iOS 通信通知 Communication Notifications 的实现

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);
    }
}
作用

至此,通讯告诉功用完成,能够测试了。咱们完成后的作用如下图:

iOS 通信通知 Communication Notifications 的实现