Skip to content

Instantly share code, notes, and snippets.

@Dexwell
Last active April 2, 2024 07:44
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Dexwell/dedef7389eae26c5b9db927dc5588905 to your computer and use it in GitHub Desktop.
Save Dexwell/dedef7389eae26c5b9db927dc5588905 to your computer and use it in GitHub Desktop.
iOS 15 Local Communication Notification
var content = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "Text"
content.sound = nil
content.categoryIdentifier = "categoryName"
var personNameComponents = PersonNameComponents()
personNameComponents.nickname = "Sender Name"
let avatar = INImage(imageData: UIImage(named: "Avatar")!.pngData()!)
let senderPerson = INPerson(
personHandle: INPersonHandle(value: "1233211234", type: .unknown),
nameComponents: personNameComponents,
displayName: "Sender Name",
image: avatar,
contactIdentifier: nil,
customIdentifier: nil,
isMe: false,
suggestionType: .none
)
let mePerson = INPerson(
personHandle: INPersonHandle(value: "1233211234", type: .unknown),
nameComponents: nil,
displayName: nil,
image: nil,
contactIdentifier: nil,
customIdentifier: nil,
isMe: true,
suggestionType: .none
)
let intent = INSendMessageIntent(
recipients: [mePerson],
outgoingMessageType: .outgoingMessageText,
content: "Test",
speakableGroupName: INSpeakableString(spokenPhrase: "Sender Name"),
conversationIdentifier: "sampleConversationIdentifier",
serviceName: nil,
sender: senderPerson,
attachments: nil
)
intent.setImage(avatar, forParameterNamed: \.sender)
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .incoming
interaction.donate(completion: nil)
do {
content = try content.updating(from: intent) as! UNMutableNotificationContent
} catch {
// Handle error
}
// Show 3 seconds from now
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
// Choose a random identifier
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
// Add notification request
UNUserNotificationCenter.current().add(request)
@Dexwell
Copy link
Author

Dexwell commented Aug 10, 2021

To get this to work, also make sure to do the following:

  • In your Notification Service Extension's Info.plist, add this: NSExtensionNSExtensionAttributes (dictionary) → IntentsSupported (array) → INSendMessageIntent (string)
  • Enable the Communication Notifications capability on your main app target
  • In Xcode, run your Notification Service Extension target and select your app to launch it with

@wilg
Copy link

wilg commented Sep 23, 2021

Do you know how to get this working with group notifications? iMessage seems to show the group icon instead of the sender icon in this case.

I cannot get it to simultaneously show both the group name and an icon for it. If I don't provide the group as an INPerson in recipients then speakableGroupName will not appear. But the INImage on the group's INPerson is never displayed, nor is the sender's image when I do this.

@Dexwell
Copy link
Author

Dexwell commented Sep 23, 2021

@wilg No idea as I haven't worked on group notifications yet, but please share if you do find out!

@lazyvar
Copy link

lazyvar commented Nov 6, 2021

Adding to what appears to be the only documentation I can find for this on the internet: I had to add INSendMessageIntent to NSUserActivityTypes key in the main Info.plist to get this to work. Having just what was described was not enough. Thanks for getting me so far @Dexwell, hopefully this can help others.

<key>NSUserActivityTypes</key>
<array>
  <string>INSendMessageIntent</string>
</array>

Signal has their implementation to peek at too which is what helped me.

@wilg Looks like they do sendMessageIntent.setImage(image, forParameterNamed: \.speakableGroupName) to get group image to work.

@lazyvar
Copy link

lazyvar commented Nov 7, 2021

OK figured out the group message thing. Two requirements:

  1. INSendMessageIntent needs to have multiple recipients. This marks the message as a "group" message.
  2. Need to call sendMessageIntent.setImage(groupImage, forParameterNamed: \.speakableGroupName)

What happens now:

  • The system will use speakableGroupName if it is set. If it is not set, the default value is the concatenation of the recipients names. So something like Mack, Doney & Will. (If you do not want this default group name to show, do not include multiple recipients in INSendMessageIntent)
  • The system will show whatever image you gave it in setImage.

Important note: An assumption I was making was that the system would create the group image for me. I thought that it would use each recipients image and make a cool looking bubble (like the one in iMessage). This is NOT true. It will simply render whatever image you give it when calling setImage. That does not mean you can't do the cool bubble thing, you just have to make it yourself.

@2jumper3
Copy link

2jumper3 commented Dec 16, 2021

Hi Dex!
Great job! Thanks a lot.

@kartikk221
Copy link

Hi, I followed your gist above and it works perfectly for local communication notifications. The problem is when I try to do the above through a Notification Service Extension to intercept and display a communication notification from my backend, the above does not work. Through debugging, I don't see any additional errors/logs that may point to a problem and documentation seems to be extremely vague for Communication Notifications. Have you been able to make Communication Notifications work through a Notification Service Extension? Thanks!

@thejeraldo
Copy link

Has anyone been able to implement multiple images for Communication Notifications like in a channel/group chat in Slack?

@lazyvar
Copy link

lazyvar commented Jul 28, 2022

@kartikk221
Make sure "mutable-content" : 1 is set in your notification payload.

@thejeraldo

Important note: An assumption I was making was that the system would create the group image for me. I thought that it would use each recipients image and make a cool looking bubble (like the one in iMessage). This is NOT true. It will simply render whatever image you give it when calling setImage. That does not mean you can't do the cool bubble thing, you just have to make it yourself.

You can do group images, but you must make the image yourself. The image being a group of images. Easiest way would be to make a custom GroupImageView: UIView and then transform that view to an image.

@thejeraldo
Copy link

@lazyvar Thanks. I thought it was a built in feature for Communication Notifications and I might've missed a configuration.
Right now I am loading the INImage with a url. And because our BE doesn't generate a thumbnail version of the user images 🙄, the images takes 1-2 seconds to show in the notification.

@phamnguyenphu
Copy link

I'm a newbie IOS
Can you help me: Where is the above code located?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment