Remote Notifications

SAPcpmsRemoteNotificationClient


Use the Remote Notification Client component to register and unregister push tokens with SAP Mobile Services. There is also an opportunity to notify the server when a notification arrives. See also: Configuring Push Notifications

Prerequisites

Configure your environment to use iOS Remote Notifications:

  1. In your Xcode project, go to App Settings -> General and change the Bundle Identifier to something unique.
  2. Go to App Settings -> Capabilities and set the switch for Push Notifications to On. This creates the App ID in your member center and adds the push notifications entitlement to it.
  3. Log in to your Apple Developer Member Center and go to Certificates, Identifiers & Profiles -> Identifiers -> App IDs and select the App ID for your app. Follow the steps to download the certificate.
  4. From the SAP Mobile Services cockpit, configure the application to use your Push Notification certificate. See: Apple Push Notifications
  5. (optional) To support silent remote notifications, add the remote-notification value to the UIBackgroundModes array in your Info.plist file. See: Remote Notification Payload

Usage

To use the SAPcpmsRemoteNotificationClient component:

  1. Create a SAPcpmsRemoteNotificationClient
  2. Register for remote notifications
  3. Register the device token with SAP Mobile Services
  4. (optional) Unregister the device token from SAP Mobile Services
  5. Send a notification
  6. (optional) Provide information about the notification status

1. Create a SAPcpmsRemoteNotificationClient

There are two way the initialize SAPcpmsRemoteNotificationClient:

a) (recommended) If you are connecting to SAP Mobile Services directly, you can use SAPcpmsSettingsParameters to initialize the SAPcpmsRemoteNotificationClient. The SAPURLSession must be configured according to your authentication settings:

// create SAPURLSession
let urlSession = SAPURLSession()

// create SAPcpmsRemoteNotificationClient
let settingsParameters = SAPcpmsSettingsParameters(backendURL: <#your baseURL#>, applicationID: <#your ApplicationID#>, deviceID: <#your DeviceID#>)
let remoteNotificationClient = SAPcpmsRemoteNotificationClient(sapURLSession: urlSession, settingsParameters: settingsParameters)

b) If you are not connecting directly to SAP Mobile Services, pass your custom URL to the SAPcpmsRemoteNotificationClient. The SAPURLSession must be configured according to your authentication settings:

// create URLs
let url = URL(string: <#your token registration url#>)!
let feedbackUrl = URL(string: <#your feedback url#>)!

// create SAPURLSession
let urlSession = SAPURLSession()

// create SAPcpmsRemoteNotificationClient with custom URL
let remoteNotificationClient = SAPcpmsRemoteNotificationClient(sapURLSession: urlSession, destinationURL: url, feedbackURL: feedbackUrl)    

2. Register for remote notifications

Obtain the users’s permission to display any kind of notification. It’s important to call the registerForRemoteNotifications method of the iOS every time the application launches because the user can change the notification permissions in the Settings at a later time:

UIApplication.shared.registerForRemoteNotifications()
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
    // Enable or disable features based on authorization.
}

This ensures that the user sees a prompt asking for permission to receive notifications. The registerForRemoteNotifications method of the iOS results in either:
application:didRegisterForRemoteNotificationsWithDeviceToken
or
application:didFailToRegisterForRemoteNotificationsWithError
being called on the application delegate.

3. Register the device token with SAP Mobile Services

When you registered for remote notifications, you passed the deviceToken to the registerDeviceToken method, which handles token registration/updating with SAP Mobile Services. A successful registration results in a completion block where the error parameter is nil:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    remoteNotificationClient.registerDeviceToken(deviceToken) { error in
        // error handling
        // ...
    }
}

You can also add optional parameters to your device token registration to help filter between registrations:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let parameters = SAPcpmsRemoteNotificationParameters(deviceType: <#your deviceType#>, pushGroup:<#your pushGroup#>, userLocale:<#your userLocale#>, timeZone:<#your timeZone#>)
    remoteNotificationClient.registerDeviceToken(deviceToken, withParameters: parameters) { error in
        // error handling
        // ...
    }
}

This can be useful when sending notifications to a specific group of devices.

4. (optional) Unregister the device token from SAP Mobile Services

In some cases it may be neccessary to remove the last uploaded token. For example, if the token cannot be provided by the OS upon a second launch, or if the user no longer wants to receive notifications. If unregisterDeviceToken completes succesfully, then the completion block’s error parameter is nil:

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
    remoteNotificationClient.unregisterDeviceToken { error in
        // error handling
        // ...
    }
}

5. Send a notification

Notifications can be sent from the SAP Mobile Services cockpit, see Sending a Push Desk Notification.

6. (optional) Provide information about the notification status

It is possible to provide notification status to the server and monitor the messages from SAP Mobile Services Cockpit.

When a new notification arrives the didReceiveRemoteNotification delegate is called by the OS. At this point you can pass the userInfo parameter to the updateNotificationStatus method and the server will be notified that the current message arrived. If updateNotificationStatus completes succesfully, then the completion block’s error parameter is nil:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
     remoteNotificationClient.updateNotificationStatus(userInfo: userInfo, completionHandler: { error in
        // error handling
        // ...
     })
}

You can track the status of any notification from the SAP Mobile Services Cockpit Reporting menu: see Viewing Push Statistics.

Note: consumed is always the status on iOS when a message arrives, because there is no other delegate in the system to use the received status. More statuses are available on other platforms.

RemoteNotificationClient component Logger ID

This component uses the following name prefix for logging: ‘SAP.Foundation.RemoteNotificationClient’

Subscribe to Push Notifications

Applications created using the {{ sdk.ios }} can subscribe to specific push notifications based on a user’s topics of interest, such as patches, new features, or security, for example. Topics may be considered to be part of the relationship between mobile apps and the notification producer for those given topics. The SDK supports customizing this relationship by allowing users to subscribe to certain topics while ignoring others. With this feature, a device can receive notifications only for the subscribed topics and avoid unwanted app notifications.

The SDK provides the following methods for subscriptions:

Get all Active Topic Subscriptions

The mobile application can retrieve all active subscriptions using the getAllSubscribedTopics method. This method returns an array of subscribed topics if available. If there is a failure, it throws an error. An example of failure is if the device ID and user are not registered for push or even when an invalid HTTP status code is returned.

Task.init {
    let remoteNotificationClient = SAPcpmsRemoteNotificationClient(sapURLSession: urlSession, settingsParameters: settingsParameters)
    do {
        let subscribedTopics = try await remoteNotificationClient.getAllSubscribedTopics()
        // Handle the response
    } catch {
        logger.error("Failed to retrieve a list of active topic subscriptions, error: \(error)")
    }
}

For convenience, getAllSubscribedTopics can also be called on the onboardingSession object:

Task.init {
    let session = sessionManager.onboardingSession
    do {
        let subscribedTopics = try await session.getAllSubscribedTopics()
        // Handle the response
    } catch {
        logger.error("Failed to retrieve a list of active topic subscriptions, error: \(error)")
    }
}

Subscribe to a Topic

Mobile applications can subscribe to a new topic using the subscribe(to topic: String) method. The String parameter is the topic name to subscribe to. This method throws an error in the case of any failure. An example of failure is if the topic is longer than 64 characters or if 32 topics are subscribed, since it is the maximum subscription limit.

Task.init {
    let remoteNotificationClient = SAPcpmsRemoteNotificationClient(sapURLSession: urlSession, settingsParameters: settingsParameters)
    do {
        try await remoteNotificationClient.subscribe(to: "Topic1")
    } catch {
        logger.error("Failed to subscribe to topic, error: \(error)")
    }
}

For convenience, subscribe(to topic: String) can also be called on the onboardingSession object:

Task.init {
    let session = sessionManager.onboardingSession
    do {
        try await session.subscribe(to: "Topic1")
    } catch {
        logger.error("Failed to subscribe to topic, error: \(error)")
    }
}

Unsubscribe From a Topic

Mobile applications can unsubscribe from a topic using the unsubscribe(from topic: String) method. The String parameter is the topic name to unsubscribe from. This method throws an error in the case of any failure.

Task.init {
    let remoteNotificationClient = SAPcpmsRemoteNotificationClient(sapURLSession: urlSession, settingsParameters: settingsParameters)
    do {
        try await remoteNotificationClient.unsubscribe(from: "Topic1")
    } catch {
        logger.error("Failed to unsubscribe from topic, error: \(error)")
    }
}

For convenience, unsubscribe(from topic: String) can also be called on the onboardingSession object:

Task.init {
    let session = sessionManager.onboardingSession
    do {
        try await session.unsubscribe(from: "Topic1")
    } catch {
        logger.error("Failed to unsubscribe from topic, error: \(error)")
    }
}
  • This class is an API to upload an APNS device token that was retrieved using Apple’s AppDelegate method application:didRegisterForRemoteNotificationsWithDeviceToken delegate to SAPcpms
    Usage sample:

    // create URLs
    let url = URL(string: <#your token registration url#>)!
    let feedbackUrl = URL(string: <#your feedback url#>)!
    
    // create SAPURLSession
    let urlSession = SAPURLSession()
    
    // create SAPcpmsRemoteNotificationClient with custom URL
    let remoteNotificationClient = SAPcpmsRemoteNotificationClient(sapURLSession: urlSession, destinationURL: url, feedbackURL: feedbackUrl)
    
    // when you received your APNS token in didRegisterForRemoteNotificationsWithDeviceToken delegate, you can upload it to SAPcpms using the registerDeviceToken method
    remoteNotificationClient.registerDeviceToken(deviceToken) { error in
    // error handling ...
    }
    
    See more

    Declaration

    Swift

    public class SAPcpmsRemoteNotificationClient
  • Enum which covers all Errors occuring in the RemoteNotificationClient.

    See more

    Declaration

    Swift

    public enum SAPcpmsRemoteNotificationError : Error
    extension SAPcpmsRemoteNotificationError: SAPError
  • RemoteNotificationParameters can be used to add more parameters to a device registration. It might be useful for filtering on the SAPcpms cockpit Push Desk screen, before sending a message to group of devices.

    See more

    Declaration

    Swift

    public struct SAPcpmsRemoteNotificationParameters