OneSignal-iOS-SDK icon indicating copy to clipboard operation
OneSignal-iOS-SDK copied to clipboard

iOS 15 Communication Notification support

Open gopricy opened this issue 2 years ago • 11 comments

This isn't a bug report but more a feature request. From this link, iOS 15 brought communication notifications which is used by slack, spark, instagram etc.

I am curious on the support plan of OneSignal iOS sdk for Comminuication Notification feature.

gopricy avatar Mar 29 '22 21:03 gopricy

@gopricy Hello thank you for reaching out. I would expect communication notifications to come from and be delivered to users of your app rather than being sent from OneSignal's dashboard. What features in particular would you like OneSignal to support for these notifications?

emawby avatar Mar 29 '22 22:03 emawby

@emawby Thanks for the quick response. We have an Instagram like app. Whenever a user create a post, all his subscribers should receive a notification. We want to use author's avatar as the notification icon utilizing the new Communification Notification feature.

We mainly use OneSignal API to send all notifications instead of through the dashboard, and we didn't find a customized avatar option in OneSignal API.

gopricy avatar Mar 30 '22 04:03 gopricy

@emawby is there any plan to support this use case in the future?

gopricy avatar Apr 25 '22 17:04 gopricy

Any hope of ever having this? 🥺

Dajust avatar Apr 01 '23 21:04 Dajust

I would also love this feature.

tcaish avatar Oct 23 '23 21:10 tcaish

Yes me too !

maximilien0405 avatar Oct 29 '23 11:10 maximilien0405

Hi all, thanks for checking in, You should be able to enable Communication Notifications yourselves by following Apple's guide.

nan-li avatar Oct 30 '23 03:10 nan-li

@nan-li This does not work for Expo-managed React Native apps since we do not have access to Apple's native programming language and system.

tcaish avatar Oct 30 '23 10:10 tcaish

I also need this feature!

gpminsuk avatar Dec 14 '23 23:12 gpminsuk

Sharing my code that I managed to work following the guide. This is NotificationService.swift file of the OneSignalNotificationServiceExtension

I am sending notifications using OneSignal REST API and didn't know where to add additional information needed for the photo url and person name, so I added to additional data structure myself which is in userInfo["custom"]["a"]

import UserNotifications
import Intents
import OneSignalExtension

class NotificationService: UNNotificationServiceExtension {
    
    private var contentHandler: ((UNNotificationContent) -> Void)?
    private var receivedRequest: UNNotificationRequest?
    private var bestAttemptContent: UNMutableNotificationContent?

    private func genMessageIntent(from request: UNNotificationRequest) -> INSendMessageIntent? {
        guard let custom = request.content.userInfo["custom"] as? [String: Any],
              let a = custom["a"] as? [String: Any],
              let name = a["name"] as? String,
              let urlString = a["url"] as? String,
              let url = URL(string: urlString) else {
            return nil
        }

        let handle = INPersonHandle(value: nil, type: .unknown)
        let avatar = INImage(url: url)
        let sender = INPerson(personHandle: handle, nameComponents: nil, displayName: name, image: avatar, contactIdentifier: nil, customIdentifier: nil)

        return INSendMessageIntent(
            recipients: nil,
            outgoingMessageType: .outgoingMessageText,
            content: nil,
            speakableGroupName: nil,
            conversationIdentifier: nil,
            serviceName: nil,
            sender: sender,
            attachments: nil
        )
    }
    
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.receivedRequest = request
        self.contentHandler = contentHandler
        self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        guard let intent = genMessageIntent(from: request) else {
            forwardRequestToExtension()
            return
        }

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

        interaction.donate { [weak self] error in
            guard let self = self, error == nil else { return }

            do {
                let content = try request.content.updating(from: intent)
                self.bestAttemptContent = (content.mutableCopy() as? UNMutableNotificationContent)
                self.forwardRequestToExtension()
            } catch {
                // Handle errors appropriately
            }
        }
    }

    private func forwardRequestToExtension() {
        guard let receivedRequest = receivedRequest, let bestAttemptContent = bestAttemptContent else { return }
        OneSignalExtension.didReceiveNotificationExtensionRequest(receivedRequest, with: bestAttemptContent, withContentHandler: contentHandler)
    }
    
    override func serviceExtensionTimeWillExpire() {
        guard let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent else { return }
        OneSignalExtension.serviceExtensionTimeWillExpireRequest(receivedRequest!, with: bestAttemptContent)
        contentHandler(bestAttemptContent)
    }
}

In addition to that I needed to add this in plist

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

gpminsuk avatar Dec 15 '23 01:12 gpminsuk

@gopricy @Dajust @tcaish I was able to implement Communication Notifications with the help of @gpminsuk's example code. I wrote a full guide for it, but keep in mind that this will not work with expo-managed apps since you need to edit NotificationService.swift in the native iOS project.

Guide: https://medium.com/@christopher.mathews/ios-communication-notifications-for-react-native-with-onesignal-35c83e75e24f

globemediaofficial avatar Dec 30 '23 07:12 globemediaofficial