iOS 15 Communication Notification picture not shown
Asked Answered
R

3

11

I've been trying to update my (local & push) notifications to Communication notifications.

When a user receives a communication event from one of their friend, I want the displayed notification to include the friend's profile picture. Just like the new iMessage app does.

After watching the dedicated WWDC2021 session, I added a Siri Intent to my SwiftUI app:

// I correctly added the StartCallIntent to both my app's Info.plist and the Siri Intent extension.
<array>
    <string>INStartCallIntent</string>
</array>

and tried to update my notification flow with the following:

let image = INImage(imageData: friend.profilePicture.cellImage.pngData()!)
let intentFriend = INPerson(
  personHandle: INPersonHandle(value: friend.phoneNumber, type: .phoneNumber),
  nameComponents: friend.nameComponents,
  displayName: friend.localName,
  image: image,
  contactIdentifier: nil,
  customIdentifier: nil,
  isMe: false,
  suggestionType: .instantMessageAddress
)

let incomingCommunicationIntent = INStartCallIntent(
  callRecordFilter: nil,
  callRecordToCallBack: nil,
  audioRoute: .unknown,
  destinationType: .normal,
  contacts: [intentFriend],
  callCapability: .audioCall
)

let interaction = INInteraction(intent: incomingCommunicationIntent, response: nil)
interaction.direction = .incoming
interaction.donate(completion: nil)

do {
  let result = try notification.updating(from: incomingCommunicationIntent)
  return result
} catch let error {
  print("-- \(error)")
  // TODO: Handle error here
}

return notification

The returned UNNotificationContent is then handled to be displayed either as a push notification or a local one.

While the above code doesn't crash and seems to /work/, the notification doesn't look any different. Looking with a debugger, the _UNNotificationCommunicationContext is initialized, but:

  • _displayName is nil
  • _recipients is empty (as expected)
  • _contentURL is nil
  • _attachments is empty
  • sender is set to a UNNotificationContact on which
    • handle & displayName are correctly set
    • _handleType seems correctly set too

In the app's logs, I can see:

[Intents] -[INCache cacheableObjectForIdentifier:] Unable to find cacheable object with identifier EDB29166-E46A-CF23-AB27-8B61F763A039 in cache.
[Intents] -[INCache cacheableObjectForIdentifier:] Unable to find cacheable object with identifier intents-remote-image-proxy:?proxyIdentifier=EDB29166-E46A-CF23-AB27-8B61F763A039.png&storageServiceIdentifier=com.apple.Intents.INImageServiceConnection in cache.

What am I missing to correctly display the friend's profile picture?

Thank you

Restricted answered 30/6, 2021 at 16:24 Comment(0)
M
14

Unfortunately Apple did not do a great job at documenting communication notifications, their WWDC video leaves a ton of very important details out, but there are a few things:

  1. In your Notification Service Extension's Info.plist you need to add this: NSExtension -> NSExtensionAttributes (dict) -> IntentsSupported (array) -> INSendMessageIntent or INStartCallIntent.

  2. Make sure you enabled the "Communication Notifications" capability on your main app target.

  3. Finally, your code looks right but you need to add this (note: I have only tested this for INSendMessageIntent)

// Swift
incomingCommunicationIntent.setImage(image, forParameterNamed: \.sender)

// Objective-C
[incomingCommunicationIntent setImage:image forParameterNamed:"sender"];
Matriculation answered 8/8, 2021 at 22:25 Comment(8)
Thanks a lot for your help! There is a slight mistake with the Swift code, I guess you wanted to simply type \.sender Also, I had issues because I was running iOS 15 Beta 2. When I upgraded to Beta 4, everything started working. Out of curiosity, how did you find this solution? Trial/guess ?Eveliaevelin
Thanks nightsd01! Also I found that in testing on iOS 15 Beta 6, initializing INImage with image data works great, but not when initializing with a remote image url.Anklet
@Anklet If you are dispatching async the code will exit the function and will not execute the completion. Make sure you dispatch sync.Slating
I've done all of the above, but still getting the "unable to find object with identifier in cache" error.Noellenoellyn
@johnnykehr Here's a great gist with a Swift example, by @Dexwell It's also worth noting the above solution seems to work starting from iOS 15 Beta 4Eveliaevelin
Thanks for this! As I mentioned in https://mcmap.net/q/1016864/-using-a-group-icon-with-ios-15-communication-notifications you can use incomingCommunicationIntent.setImage(image, forParameterNamed: \.speakableGroupName) to show the group image in group messages :DDerzon
@johnnykehr I'm in the same situation you was in. Do you have any resolution on communication notification with remote image URL? ThanksFaery
@AlexTerente could you please specify in code what that means. I can not figure out how to display an image from a remote url. Whatever i tried it did not show up ...Hamrah
A
1

For those who's confused like I was, the INSendMessageIntent key has to be added under NSUserActivityTypes in the plist file in the main target, like this:

<key>NSUserActivityTypes</key>
<array>
  <string>INSendMessageIntent</string>
</array>
Axil answered 18/1, 2022 at 13:57 Comment(0)
F
0

For those who has problems with URL inutializing use this:

extension INImage {
    convenience init?(contentsOf url: URL) {
        if let data = try? Data(contentsOf: url) {
            self.init(imageData: data)
        } else {
            return nil
        }
    }
}

It feels like workaround, but works.

Found it somhere on web, but lost the source, sry

Factitious answered 28/2, 2023 at 16:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.