Start enriching your app
No Credit Card Required

Docs

iOS
  • Introduction

    The Sinch SDK is a product that makes adding voice calling and/or instant messaging to mobile apps easy. It handles the complexity of signaling and audio management while providing you the freedom to create a stunning user interface.

    This document provides an overview for developers integrating with Sinch SDK for the first time. It outlines the prerequisites and guides you through the process of setting up and answering calls as well as sending and receiving instant messages.

    Please see the Reference Documentation for a comprehensive description of all the classes.

    First time setup

    This is a step-by-step guide about setting up the Sinch SDK for the first time.

    Register an Application

    1. Register a Sinch Developer account at http://www.sinch.com/signup.
    2. Setup a new Application using the Dashboard where you can then obtain an Application Key and an Application Secret.

    Download

    The Sinch SDK can be downloaded at www.sinch.com/download/. It contains: the library binary, this user guide, reference documentation, and sample apps for calling and instant messaging.

    Sinch is available as a CocoaPod

    If you are using CocoaPods, add the following to your Podfile:

    target '<your xcode project>' do
      pod 'SinchRTC'
    end
    

    Tip: Using the pod allows you to skip the manual steps in the next section.

    Add the Sinch.framework

    Drag the Sinch.framework bundle from the SDK distribution package folder into the Frameworks section in the Xcode Project Navigator.

    The Sinch SDK depends on the following frameworks which must be linked with the application target:

    libc++.dylib (libc++.tbd), libz.tbd, Security.framework, AVFoundation.framework, AudioToolbox.framework, VideoToolbox.framework, CoreMedia.framework, CoreVideo.framework, CoreImage.framework, GLKit.framework, OpenGLES.framework, QuartzCore.framework

    Info.plist

    If only the instant messaging functionality will be used, then no changes to the Info.plist are necessary.

    If voice calling functionality will be enabled and used, add the following to your Info.plist:

    • Required background modes (UIBackgroundModes):
      • Application plays audio (audio)
      • Application provides Voice over IP services (voip)
    • Privacy - Microphone Usage Description (NSMicrophoneUsageDescription):

      NSMicrophoneUsageDescription describes the reason your app accesses the microphone. When the system prompts the user to allow access, this string is displayed as part of the alert, and it cannot be left empty.

    In addition to the keys above, if video calling functionality will be enabled and used, add the following to your Info.plist:

    • Privacy - Camera Usage Description (NSCameraUsageDescription):

      NSCameraUsageDescription describes the reason that your app accesses the camera. When the system prompts the user to allow access, this string is displayed as part of the alert, and it cannot be left empty.

    Sinch client

    The SINClient is the Sinch SDK entry point. It is used to configure the user’s and device’s capabilities, as well as providing access to feature classes such as the SINCallClient, SINMessageClient and SINAudioController.

    Creating the SINClient

    Set up the client and its delegate (SINClientDelegate, see Reference documentation).

    #import <Sinch/Sinch.h>
    
    // Instantiate a Sinch client object
    id<SINClient> sinchClient = [Sinch clientWithApplicationKey:@"<application key>" 
                                              applicationSecret:@"<application secret>"
                                                environmentHost:@"sandbox.sinch.com" 
                                                         userId:@"<user id>"];
    

    The Application Key and Application Secret are obtained from the Sinch Developer Dashboard. See Production and Sandbox Environments for valid values for environmentHost. The User ID should uniquely identify the user on the particular device.

    Specifying capabilities

    The SINClient can be configured to enable / disable certain functionality. Please see the Reference for details.

    The following example shows how to setup the client with both voice calling and instant messaging enabled, and using push notifications.

    // Specify the client capabilities. 
    // (At least one of the messaging or calling capabilities should be enabled.)
    [sinchClient setSupportCalling:YES];
    [sinchClient setSupportMessaging:YES];
    
    [sinchClient enableManagedPushNotifications];
    

    Starting the Sinch client

    Before starting the client, make sure you assign a SINClientDelegate.

    // Assign as SINClientDelegate                             
    sinchClient.delegate = ... ;
    
    // Start the Sinch Client
    [sinchClient start];
    
    // Start listening for incoming calls and messages
    [sinchClient startListeningOnActiveConnection];
    

    Note: If the application is meant to only make outgoing calls but not receive incoming calls, don’t call the startListeningOnActiveConnection. Outgoing calls can be made after calling the start method, and after the delegate has received the callback clientDidStart:.

    For applications that want to receive incoming calls while not running in the foreground, push notifications are required.

    Life cycle management of a SINClient-instance

    We recommend that you initiate the Sinch client, start it, but not terminate it, during the lifetime of the running application. That also implies that the SINClient-instance should be retained by the application code.

    If incoming events are not needed, stop listening for incoming events by invoking -[SINClient stopListeningOnActiveConnection]), but do not invoke -[SINClient terminateGracefully] or -[SINClient terminate]. The reason is initializing and starting the client is relatively resource-intensive in terms of CPU.

    It is best to keep the client instance alive and started unless there are reasons specific to your application. It should not be necessary to dispose of the client instance if memory warnings are received from iOS, because once the client is started it does not use much memory in comparison to view layers, view controllers etc. For the same reasons, if support for push notifications is enabled, the preferred method of temporarily stopping incoming events is to Unregister a push device token.

    The Sinch client can of course be completely stopped and also disposed. To do so, call one of the terminate methods on the client before the application code releases its last reference to the client object.

    The following example shows how to dispose the Sinch client:

    [sinchClient stopListeningOnActiveConnection];
    [sinchClient terminateGracefully]; // or invoke -[SINClient terminate]
    sinchClient = nil;
    

    Calling

    The Sinch SDK supports four types of calls: app-to-app (audio or video), app-to-phone, app-to-sip and conference calls. The SINCallClient is the entry point for the calling functionality of the Sinch SDK.

    Calls are placed through the SINCallClient and events are received using the SINCallClientDelegate. The call client is owned by the SinchClient and accessed using [sinchClient callClient]. Calling is not enabled by default.

    Enable calling with the following method before starting the SINCallClient:

    [sinchClient setSupportCalling:YES];    
    

    Setting up an app-to-app call

    Use the call client to start the call using the callUserWithId: method by passing the user identifier of the callee (the user receiving a call) as an argument.

    id<SINCallClient> callClient = [sinchClient callClient];
    id<SINCall> call = [callClient callUserWithId:@"<remote user id>"];
    // Or for video call: id<SINCall> call = [callClient callUserVideoWithId:@"<remote user id>"];
    

    A call object is returned, containing details about the participants in the call, call details such as start time, call state, possible errors, and so on.

    Assuming the callee’s device is available and responsive, the delegate method callDidProgress: is called. It notifies the application that the outgoing call is progressing. If a progress tone should be played, this is where it should be started. We recommend that you use the available functionality provided by the Sinch SDK to play sounds such as ringtones (SINAudioController). See Playing Ringtones for details.

    When the other party answers, the callDidEstablish: call delegate method is called. Now, the users can start talking. If a progress tone has been initiated, it should be stopped now, in the delegate callback method.

    Setting up an app-to-phone call

    An app-to-phone call is a call that is made to a phone on the regular telephone network. Setting up an app-to-phone call is not much different from setting up an app-to-app call.

    Instead of invoking the callUserWithId: method, invoke the callPhoneNumber: method on the SINCallClient object. Sufficient funds must be available on the Sinch account and a valid phone number specified for the call to connect successfully. The phone number should be specified according to the E.164 number formatting (http://en.wikipedia.org/wiki/E.164) recommendation and should be prefixed with a ‘+’. E.g. to call the US phone number 415 555 0101, the phone number should be specified as “+14155550101”. The ‘+’ is the required prefix and the US country code ‘1’ prepended to the local subscriber number.

    Placing an app-to-phone call requires an account with credits; topping up credits can be done on the Account page. Credits are used each time an app-to-phone call is placed and the balance history is updated after each call.

    App-to-phone calls can be tested by calling the following test number: +46000000000. When placing a call to this number, you will hear a voice prompt stating that the call has been connected, and shortly after that the call will automatically be ended.

    Setting up an app-to-sip call

    An app-to-sip call is a call that is made to a SIP server. Setting up an app-to-sip call is not much different from setting up an app-to-app call. Instead of invoking the callUserWithId: method, invoke the callSIP: method on the SINCallClient object. The SIP identity follows the form of email addresses (user@domain), for example Alice@SipProviderA.com.

    id<SINCallClient> callClient = [sinchClient callClient];
    id<SINCall> call = [callClient callSIP:@"<SIP Identity>"];
    

    When customized SIP headers are passed as a parameter, the headers should be prefixed with ‘x-’. If the SIP server reported any errors, the SINCallDetails object will provide an error with SINErrorDomainSIP.

    Setting up a conference call

    A conference call can be made to connect a user to a conference room where multiple users can be connected at the same time. The identifier for a conference room may not be longer than 64 characters.

    id<SINCallClient> callClient = [sinchClient callClient];
    id<SINCall> call = [callClient callConferenceWithId:@"<conferenceId>"];
    

    It is also possible to connect users to a conference call via the Sinch REST API.

    Handling incoming calls

    To act on the incoming calls, implement the protocol SINCallClientDelegate and assign a delegate to the call client. The call client delegate is notified using the delegate method didReceiveIncomingCall: as calls come in to the device.

    When the delegate method is executed, the call can either be connected automatically without any user action, or it can wait for the user to press the answer or the hangup button. We recommend that ringtones are played from within the delegate callback method. See Playing Ringtones for details.

    - (void)client:(id<SINCallClient>)client didReceiveIncomingCall:(id<SINCall>)call {
        // Start playing ringing tone
        ... 
    
        // Assign delegate
        call.delegate = self;
    }
    

    To get events related to the call, set the call delegate. The call object contains details about participants, start time, potential error codes, and error messages.

    If VoIP push notifications is enabled, add logic for presenting a local notification if the app is in the background when receiving the call:

    - (SINLocalNotification *)client:(id<SINClient>)client 
      localNotificationForIncomingCall:(id<SINCall>)call {
        SINLocalNotification *notification = [[SINLocalNotification alloc] init];
        notification.alertAction = @"Answer";
        notification.alertBody = @"Incoming call";
        return notification;
    }
    

    IMPORTANT: See Local and Remote Push Notifications for further details on how to present and handle a user notification for an incoming call when the application is in the background.

    Incoming video call

    When incoming call is a video call, the didReceiveIncomingCall delegate method will be executed, just like for the incoming audio call. The SINCallDetails object provides a isVideoOffered property to check whether the call offers a video track. See the Video calling section for details on how to add video views.

    Answering an incoming call

    To answer a call, use the answer method on the call to accept it. If a ringtone was previously played, it should be stopped now.

    User presses the answer button:

    // User answers the call 
    [call answer];
    
    // Stop playing ringing tone
    ...     
    

    Now, the clients on both ends establish the connection. When the call is established and the voice streams are running in both directions, the callDidEstablish: delegate method is called.

    Declining an incoming call

    If the call should not be answered, use the hangup method on the call to decline. The caller is notified that the incoming call was denied. If a ringtone was previously played, it should be stopped now.

    User presses the hangup button:

    // User does not want to answer
    [call hangup];
    
    // Stop playing ringing tone
    ...     
    

    Disconnecting a call

    When the user wants to disconnect an ongoing call, use the hangup method. Either user taking part in a call can disconnect it.

    Hanging up a call:

    [call hangup];
    

    When either party disconnects a call, the application is notified using the call delegate method callDidEnd:. This allows the user interface to be updated, an alert tone to be played, or similar actions to occur.

    A call can be disconnected before it has been completely established.

    Hanging up a connecting call:

    // Starting a call
    id<SINCall> call = [client callUserWithId:@"<remote user id>"];
    
    // User changed his/her mind, let’s hangup
    [call hangup];
    

    Handling a call that ends:

    // SINCallDelegate implementation
    
    - (void)callDidEnd:(id<SINCall>) call {
      // update user interface, e.g. hide the call screen.
    }
    

    Video calling

    Setting up a video call

    Just like audio calls, video calls are placed through the SINCallClient and events are received using the SINCallClientDelegate. The call client is owned by the SinchClient and accessed using [sinchClient callClient]. Calling is not enabled by default. For a more general introduction to calling with the SinchClient, see Calling.

    Showing the video streams

    The following examples for showing video streams will be based on the assumption of a view controller having the following properties:

    @interface MyViewController : UIViewController
    
    @property (weak, nonatomic) IBOutlet UIView *remoteVideoView;
    @property (weak, nonatomic) IBOutlet UIView *localVideoView;
    
    @end
    

    Showing a preview of the local video stream

    - (void)viewDidLoad {
      [super viewDidLoad];
    
      id<SINVideoController> videoController = ... // get video controller from SINClient.
    
      [self.localVideoView addSubview:[self.videoController localView]];
    }
    

    Showing remote video streams

    Once you have created a SINCallClientDelegate and added it to a call, the method callDidAddVideoTrack: will be called.

    - (void)callDidAddVideoTrack:(id<SINCall>)call {
      id<SINVideoController> videoController = ... // get video controller from SINClient.
    
      // Add the video views to your view hierarchy
      [self.remoteVideoView addSubview:[videoController remoteView]];
    }
    

    Pausing video stream

    To pause the local video stream, use the pauseVideo method on the call.

    // Pause the video stream.
    [call pauseVideo];
    

    Resuming video stream

    To resume the local video stream, use the resumeVideo method on the call.

    // Resume the video stream. 
    [call resumeVideo];
    

    Pausing video stream delegates

    Once you have created a SINCallClientDelegate and added it to a call, the method callDidPauseVideoTrack: will be called when the remote user pause the video stream.

    - (void)callDidPauseVideoTrack:(id<SINCall>)call {
      // Implement what to be done when remote user pause video stream.
    }
    

    Resuming video stream delegates

    Once you have created a SINCallClientDelegate and added it to a call, the method callDidResumeVideoTrack: will be called when the remote user resumes the video stream.

    - (void)callDidResumeVideoTrack:(id<SINCall>)call {
      // Implement what to be done when remote user resumes video stream.
    }
    

    Video content fitting and aspect ratio

    How the rendered video stream is fitted into a view can be controlled by the regular -[UIView contentMode] property. I.e. assigning contentMode on a view returned by -[SINVideoController remoteView] or -[SINVideoController localView] will affect how the video content is laid out. Note though that only UIViewContentModeScaleAspectFit and UIViewContentModeScaleAspectFill will be respected.

    Example:

    id<SINVideoController> videoController;
    videocontroller.remoteView.contentMode = UIViewContentModeScaleAspectFill;
    
    

    Full screen

    The Sinch SDK provides helper functions to transition a video view into fullscreen mode. These are provided as Objective-C category methods for the UIView class and are defined in SINUIView+Fullscreen.h (SINUIViewFullscreenAdditions).

    Example:

    - (IBAction)toggleFullscreen:(id)sender {
        id<SINVideoController> videoController = ... // get video controller from SINClient.
    
        UIView *view = videoController.remoteView;
        
        if ([view sin_isFullscreen]) {
          view.contentMode = UIViewContentModeScaleAspectFit;
          [view sin_disableFullscreen:YES]; // Pass YES to animate the transition
        } else {
          view.contentMode = UIViewContentModeScaleAspectFill;
          [view sin_enableFullscreen:YES];  // Pass YES to animate the transition
        }
      }
    

    Accessing video frames of the remote streams

    The Sinch SDK provides developers a callback to access the video frames of the remote streams. So you can process the video frames with your own implementation to achieve rich functionalities, e.g., applying filters, adding stickers to the video frames, or saving the video frame as an image.

    Your video frame handler needs to conform SINVideoFrameCallback protocol by implementing the onFrame: callback. Note that you need to explicitly release the video frame by calling [videoFrame releaseFrame].

    Examples:

    // YourVideoFrameHandler.h
    // Conform SINVideoFrameCallback protocol
    @interface YourVideoFrameHandler : NSObject<SINVideoFrameCallback>
        ... // Handler specific declarations
    @end
    
    // YourVideoFrameHandler.m
    // Implement onFrame: callback
    @implementation YourVideoFrameHandler
    - (void)onFrame:(id<SINVideoFrame>)videoFrame callId:(NSString *)callId {
      ... // Process videoFrame
      [videoFrame releaseFrame]; // Release videoFrame
    }
    @end
    

    Use -[SINVideoController setVideoFrameCallback:] to register your video frame handler as the callback to receive video frames.

    Example:

    YourVideoFrameHandler* videoFrameHandler;
    id<SINVideoController> videoController = ... // Get video controller from SINClient.
    [videoController setVideoFrameCallback: videoFrameHandler];
    

    Converting video frame to UIImage

    The Sinch SDK provides helper functions to convert id<SINVideoFrame> to UIImage*. It is handy to get the UIImage representation of SINVideoFrame by calling function SINUIImageFromVideoFrame(). Note that the helper function will NOT release the video frame.

    Example:

    #import "SINVideoController.h" // To use SINUIImageFromVideoFrame()
    
    id<SINVideoFrame> videoFrame = ... // Get SINVideoFrame from onFrame: callback
    UIImage *image = SINUIImageFromVideoFrame(videoFrame);
    

    Instant messaging

    The SINMessageClient is the entry point to Instant Messaging functionality in the Sinch SDK.

    Messages are sent through the SINMessageClient and events are received by the SINMessageClientDelegate. The message client is owned by the SINClient and accessed via -[SINClient messageClient]. Instant messaging is not enabled by default. In order to enabled instant messaging, - [SINClient setSupportMessaging: YES] must be set.

    SINClient sinchClient;
    [sinchClient setSupportMessaging: YES];
    SINMessageClient messageClient = [sinchClient messageClient];
    
    // Assign a delegate for instant messages events
    messageClient.delegate = ...
    

    Sending a message

    Messages are created using the static method +[SINOutgoingMessage messageWithRecipient:text:]. Once created, sending the message is as simple as calling -[SINMessageClient sendMessage:]:

    SINOutgoingMessage *message = [SINOutgoingMessage messageWithRecipient:@"<recipient user id> text:@"Hi there!"];
    
    [messageClient sendMessage:message];
    

    Message delivery success

    When a message to a recipient is successfully sent, the delegate is notified:

    // SINMessageClientDelegate
    
    - (void) messageSent:(id<SINMessage>)message recipientId:(NSString *)recipientId{
      // Persist outgoing message
      // Update UI
    }
    

    Updating the UI from the messageSent: callback is especially convenient when a user is simultaneously logged into more than one device. The messageSent: callback is fired on each device. This aids in keeping the UI consistent across devices.

    As soon as the system has confirmed the messages were delivered, the delegate is notified using the messageDelivered:method. Inspecting the infoparameter passed to the callback reveals more details about the event.

    - (void) messageDelivered:(id<SINMessageDeliveryInfo>)info {
       NSLog(@"Message with id %@ was delivered to recipient with id  %@",
                                                   info.messageId,
                                                   info.recipientId);
    }
    

    Message delivery failures

    Delivering a message can fail for various reasons: there might not be a network available, the recipient does not have instant messaging support, and so on. When a message failed to reach its destination the delegate is notified using the messageDeliveryFailed: callback. The reason for failing to deliver a message is propagated back as an array of SINMessageFailureInfo instances.

    - (void) messageDeliveryFailed:(id<SINMessage>) message info:(NSArray *)messageFailureInfo {
        for (id<SINMessageFailureInfo> reason in messageFailureInfo) {
            NSLog(@"Delivering message with id %@ failed to user %@. Reason %@", 
            reason.messageId, reason.recipientId, [reason.error localizedDescription]);
        }
    }
    

    Note: Messages are persisted internally in the SDK. In case the message was not sent successfully it will be retried automatically at a later point in time. The message will be retried for 12 hours and then fail permanently firing the failure callback.

    Note: Messages are stored in the backend for 30 days before being removed. If the recipient has not started the app and downloaded the message history within this time, the message will be lost and no notification received.

    Note: A message should be retried only in case of network unavailability (use [[failureInfo.error domain] isEqualToString:SINErrorDomainNetwork]). In this case, create a new instance of SINOutgoingMessage (using +[SINOutgoingMessage messageWithMessage:]) and send that instance because the previous message is considered stale.

    Receiving a message

    Incoming messages are delivered to the delegate:

    - (void) messageClient:(id<SINMessageClient>) messageClient 
              didReceiveIncomingMessage:(id<SINMessage>)message {             
    
      // Present a Local Notification if app is in background
      if([UIApplication sharedApplication].applicationState == UIApplicationStateBackground){
    
        UILocalNotification* notification = [[UILocalNotification alloc] init];
        notification.alertBody = [NSString stringWithFormat:@"Message from %@",
                                                            [message recipientIds][0]];
    
        [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
      } else {
        // Update UI in-app
      }
    
      // Persist incoming message
    
    }
    

    Note: The application handles iOS local notifications for instant messages which is different than how incoming calls are handled. The Sinch SDK manages the local notifications for incoming calls.

    Sending a message to multiple recipients

    To send a message to multiple recipients, create the outgoing message with the +[SINOutgoingMessage messageWithRecipients:text:].

    NSArray *recipients = @[@"recipient user id 1", @"recipient user id 2"];
    SINOutgoingMessage *message = [SINOutgoingMessage messageWithRecipients:recipients text:@"Hi there!"];
    
    [messageClient sendMessage:message];
    

    Receiving status updates for multi-recipient Messages

    When a message transitions to a new state it is communicated back using SINMessageClientDelegate as the single recipient case. The delegate’s callbacks are triggered once for every recipient.

    Local and Remote Push Notifications

    When an application is no longer in the foreground, the user must be notified of an incoming call or instant message by means of either a local notification or a remote push notification.

    If the app is allowed to execute while in background then the Sinch SDK will primarily use local notifications to initially notify the user. Whether the app is allowed to execute while in background depends on whether you as a developer choose to enable VoIP push notifications and/or Active Connection in Background. If only regular remote push notifications are used then those will also be used to notify the user (as a regular remote push notification will be displayed to the user by the iOS without handing over any control to the application).

    Remote Push Notifications

    An application is considered offline in the following scenarios:

    For these scenarios, push notifications can be used to receive incoming calls and instant messages. The following sections cover how to enable receiving calls and messages using remote push notifications (both the VoIP type and regular.)

    Acquiring a device token and user consent

    SINManagedPush is a component used to simplify acquiring a push device token and registering it with a Sinch client. It also simplifies in terms of abstracting away some of the iOS SDK API differences between iOS verions and APIs, as well as differences for regular remote push notifications and VoIP push notifications.

    SINManagedPush should be created as early as possible in the application’s life-cycle (and it’s lifecycle can be independent of a SINClient’s life-cycle.)

    @interface AppDelegate () <SINManagedPushDelegate>
    @property (nonatomic, readwrite, strong) id<SINManagedPush> push;
    @end
    
    - (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        self.push = [Sinch managedPushWithAPSEnvironment:SINAPSEnvironmentAutomatic];
        self.push.delegate = self;
    
        [self.push setDesiredPushTypeAutomatically];
        [self.push registerUserNotificationSettings]; // This can be delayed to later in the app's life-cycle, e.g. once a user logs in.
    }
    

    NOTE: When creating the managed push instance, the Apple Push Service Environment (also referred to as APS Environment) must be specified and it must match how your application is code signed and provisioned. Please see the section Apple Push Service environments and provisioning for details.

    Enable push notifications on a Sinch client

    When creating a Sinch client, managed push notifications must be enabled:

    id<SINClient> client = [Sinch clientWithApplicationKey:@"<application key>" 
                                         applicationSecret:@"<application secret>"
                                           environmentHost:@"sandbox.sinch.com" 
                                                    userId:@"<user id>"];
    
    [client enableManagedPushNotifications];
    

    Forward incoming push notifications to a Sinch client

    Implement the protocol SINManagedPushDelegate and forward any incoming push notifications to a Sinch client:

    // SINManagedPushDelegate
    - (void)managedPush:(id<SINManagedPush>)unused
        didReceiveIncomingPushWithPayload:(NSDictionary *)payload
                                  forType:(NSString *)pushType {
        id<SINClient> client; // get previously created client
        [client relayRemotePushNotification:userInfo];
    }
    

    The purpose of SINManagedPushDelegate and the delegate method managedPush:didReceiveIncomingPushWithPayload:type: is that it provides a single unified code path for handling incoming push notifications, no matter whether it is a regular remote push notification or a VoIP push notification (which is received via PushKit and PKPushRegistry). In the case of a regular remote push; independently of whether it is arriving via -[UIApplicationDelegate didReceiveRemoteNotification: or as a launch option via -[UIApplication applicationDidFinishLaunching:didFinishLaunchingWithOptions:.

    Unregister a push device token

    If the user of the application logs out or performs a similar action, the push notification device token can be unregistered via -[SINClient unregisterPushNotificationDeviceToken] to prevent further notifications to be sent to the particular device.

    Supporting regular remote push notifications (i.e. non-VoIP type push notifications)

    Because of differences in the iOS SDK API with respect to regular and VoIP push notifications, incoming push notifications have different code paths through an application. SINManagedPush unifies this to the extent possible, but for regular remote notifications which are traditionally received via methods on UIApplicationDelegate, the following methods should be forwarded from the application delegate:

    - (void)application:(UIApplication *)application
        didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
            [self.push application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
    }
    
    - (void)application:(UIApplication *)application 
        didReceiveRemoteNotification:(NSDictionary *)userInfo {
            [self.push application:application didReceiveRemoteNotification:userInfo];
    }
    

    Sinch localization strings for push notification alerts

    When the Sinch platform sends a remote push notification for an incoming call or message it will by default use one of the localization strings shown below. You will need to add these to your `Localizable.strings´ file.

    SIN_INCOMING_CALL = "Incoming call";
    SIN_INCOMING_CALL_DISPLAY_NAME = "Incoming call from %@";
    SIN_INCOMING_IM = "Incoming message";
    SIN_INCOMING_IM_DISPLAY_NAME = "Incoming message from %@";
    

    SIN_INCOMING_CALL_DISPLAY_NAME (or SIN_INCOMING_IM_DISPLAY_NAME) will be used if display name have been set by the caller via -[SINManagedPush setDisplayName: or -[SINClient setPushNotificationDisplayName:]. Display name is included in a push notification on a best-effort basis. For example, if the target device has very limited push payload size constraints (e.g. iOS 7 can only handle 255 byte push notification payload), then the display name may not be included.

    (Note: This is not applicable to VoIP type push notifications because in that case the Sinch SDK will present a local notification (see -[SINCallClientDelegate client:localNotificationForIncomingCall:) )

    Please see Apple’s Local and Remote Notification Programming Guide on remote push notification and localization strings for more details.

    Presenting local notifications for incoming calls

    If the application is not in foreground when receiving an incoming call, the SINCallClient will ask it’s delegate SINCallClientDelegate to specify how a local notification should be presented. The delegate is responsible for composing a SINLocalNotification with content that is to be shown to the user when the local notification is presented to the user by iOS. The delegate can specify all things as available for a regular UILocalNotification, e.g. alert body, actions, a badge number, and the path to a sound file that is played when the notification is presented. Example:

    // implementation of SINCallClientDelegate
    - (SINLocalNotification *)client:(id<SINClient>)client 
      localNotificationForIncomingCall:(id<SINCall>)call {
        SINLocalNotification *notification = [[SINLocalNotification alloc] init];
        notification.alertAction = @"Answer";
        notification.alertBody = @"Incoming call";
        return notification;
    }
    

    If the user taps the notification, iOS brings the app back into the foreground. The notification object contains information that is needed by the Sinch SDK to continue initiating the incoming call. To hand over the notification object to the Sinch client, use the method relayLocalNotification::

    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    
        if ([notification sin_isSinchNotification]){
    
          // This will trigger -[SINClientDelegate didReceiveIncomingCall:] if the notification
          // represents a call (i.e. contrast to that it may represent an instant-message)
          id<SINNotificationResult> result = [client relayLocalNotification:notification];
    
          if (result.isCall && result.callResult.isTimedOut) {
            // The notification is related to an incoming call,
            // but was too old and the call has expired.
            // The call should be treated as a missed call and appropriate
            // action should be taken to communicate that to the user.
          }
        }
    }
    

    The SINCallNotificationResult object provides details about the caller, whether the call timed out and whether the call offers video.

    Answering a call received while in background

    Once the Sinch SDK has processed the call information extracted from the notification, it calls the delegate method client:didReceiveIncomingCall:. Depending on the desired behavior for the app, the incoming call may either be treated as any other incoming call and let the user tap an additional button to answer it, or the call may be answered automatically when the user has acted on the local notification.

    In the latter case, the app can determine whether the call originated from background mode or not by examining the applicationStateWhenReceived property of the call details object. If the application was active when it received the call, it means the app was in the foreground. This approach is also applicable to offline calls with Apple Push Notifications.

    - (void)client:(id<SINClient>)client didReceiveIncomingCall:(id<SINCall>)call {
        call.delegate = self;
    
        if (call.details.applicationStateWhenReceived == UIApplicationStateActive) {
            // Show an answer button or similar in the UI
        } else {
            // Application was in not in the foreground when the call was initially received,
            // and the user has opened the application (e.g. via a Local Notification),
            // which we then interpret as that the user want to answer the call.
            [call answer];
        }
    }
    

    Enabling VoIP push notifications

    In iOS 8 Apple introduced remote VoIP push notifications and a new framework PushKit.framework. VoIP push is more battery efficient than using an active VoIP socket, and still provides the possibility of background execution which allows for faster call setup time. The Sinch SDK supports both VoIP and regular remote push notifications.

    The Sinch SDK will automatically use VoIP push if PushKit.framework is linked into your app, given that -[SINManagedPush:setDesiredPushTypeAutomatically] is used. Using setDesiredPushTypeAutomatically will fall back to using regular remote push notifications on devices that don’t support VoIP push (e.g. devices running on iOS < 8.0).

    It is required to implement -[SINCallClientDelegate localNotificationForIncomingCall:] when using VoIP push.

    To enable VoIP push on devices that are capable of it and also fall back on regular remote notifications for iOS 6 and 7, we recommended to weak link PushKit.framework. In the Xcode target settings, go to Build Phases and the section Link Binary With Libraries and in the Status field on the right-hand side, select Optional (instead of Required):

    For more details on VoIP push notifications, see here

    Sinch local notifications and the Notification Center

    The following details explain how the Sinch SDK handles local notifications and how it affects what is presented in the Notification Center.

    • A notification that is passed in to the method -[SINClient relayLocalNotification:notification:] is removed from the Notification Center after it has been handled.
    • A local notification representing an incoming call is removed if the call times out.
    • Invoking -[SINCall hangup] from -[SINClient client:localNotificationForIncomingCall] is a valid operation and can be used to dismiss a call while the user is busy talking in the regular phone app. This effectively prevents the SDK from invoking the -[SINClientDelegate client:didReceiveIncomingCall:] method when the app returns to foreground.
    • Invoking -[SINCall answer] while being in the background is possible. The call is not immediately answered but the operation is considered pending and the call answered once the app returns to the foreground.

    Apple Push Notification Certificates

    Sending and receiving push notifications via Sinch requires you to create Apple Push Certificates and upload them to the Sinch Dashboard. For each application, Sinch allows you to upload up to three certificates corresponding, one for each type: Development, Production and VoIP Services.

    Generating Apple Push Certificates

    Apple Push Certificates are generated from the Apple Developer Member Center which requires a valid Apple ID to login. If you do not have this information, find out who manages the Apple Developer Program for your organization.

    Setting up your Apple Push Certificates with Sinch

    • Login to the Dashboard
    • Open the Apps tab, select the application of your choice and click on the Push Notification icon on the left-most side.
    • Drag and drop the certificates associated to your application
    • If your certificate has a password, enter it and hit Enter

    Your push notification certificates are now uploaded and ready for use.

    Certificates configured with Sinch can be replaced or renewed by uploading new ones. New certificates will automatically replace the previous ones for their respective type (Development, Production and VoIP Services).

    Apple Push Service environments and provisioning

    When an iOS application is code signed, it is the embedded Provisioning Profile that will specify which Apple Push Notification Service Environment (APS Environment) the acquired push notification device token will be bound to. Depending on how an application is provisioned it has an effect on what should be passed to [Sinch managedPushWithAPSEnvironment:]. For example if your application is signed with a Development provisioning profile it will be bound to the APS Development environment. If it’s code signed with a Distribution provisioning profile (also referred to as Universal) it will be bound to the APS Production environment.

    Typically a Debug build will be code signed with a Development provisioning profile and thus SINAPSEnvironmentDevelopment should be used. And typically a Release build will be code signed with a Distribution provisioning profile and thus SINAPSEnvironmentProduction should be used. Instead of changing this manually for each build, the macro SINAPSEnvironmentAutomatic is available which automatically expands to Development for Debug builds and Production for Release builds.

    Audio handling

    If the application plays audio that does not originate from the Sinch SDK, certain guidelines should be followed. Additional information on audio session-related topics is available in the Audio Session Programming Guide.

    Audio sessions

    When a call is established, the Sinch client activates the shared audio session. When the call is disconnected, the Sinch client deactivates the shared audio session. If the application wants to play audio in any other context, it needs to reactivate the shared audio session. This applies after each finished call.

    When started, the Sinch SDK client sets itself as the audio session delegate. If the application wishes to override this behavior, the application needs to reset the delegate after the client has started but before any call has been started. (Doing this is not recommended.)

    Audio session categories

    When the Sinch client is started, it sets the audio session category to PlayAndRecord. The reason the Sinch client only sets the audio category once, is to avoid interfering with what the hosting application may want to do with the audio session.

    If the application changes the audio session category, it is responsible for changing the category back to PlayAndRecord after the application has performed its audio task so that the category is correctly setup for calls.

    The Sinch SDK applies the audio session category mode AVAudioSessionModeVoiceChat for improved voice quality. Please see Apple’s AVAudioSession documentation for further details.

    Audio session interruptions

    When the users are in the midst of a Sinch SDK call, someone might call users using the PSTN network, thus interrupting the application and make iOS play the regular native ringtone. If the native phone call ends within 30 seconds, the application will start running again. If not, the Sinch SDK call will be terminated.

    Playing ringtones

    The SINAudioController object provides a convenience method startPlayingSoundFile:loop: for playing sounds that are related to a call, such as ringtones and busy tones. Details on how to use it can be found in the Reference documentation.

    The sound file must be a mono (1 channel), 16-bit, uncompressed (PCM) .wav file with a sample rate of 8kHz, 16kHz, or 32kHz.

    - (void)callReceivedOnRemoteEnd:(id<SINCall>)call {
        NSString* soundFilePath = [[NSBundle mainBundle] pathForResource:@"progresstone" ofType:@"wav"];
        // get audio controller from SINClient
        id<SINAudioController> audioController = [self.client audioController];
        [audioController startPlayingSoundFile:soundFilePath loop:NO];
    }
    

    Applications that prefer to use their own code for playing sounds are free to do so, but they should follow the guidelines for Audio Sessions and Audio Session Categories above.

    Application authentication

    A user identity must be provided when initiating a Sinch client. The first time the application instance and the Sinch client are running on behalf of a particular user, they are required to register against the Sinch service. This is mostly handled transparently by the Sinch SDK, but it works slightly differently depending on which authentication scheme you choose to use.

    The step of registering a user identity against the Sinch service requires the application instance to be authenticated and authorized to perform the user registration. Once the application instance has successfully registered the user identity, it will also have obtained the necessary credentials to perform further authorized requests for that specific user, for example, calling.

    Two different authentication schemes are available: authentication by client access to application secret and authentication supported by application server.

    Authentication by client access to Application Secret

    This application authentication scheme is based on giving the application direct access to the Application Secret, which enables the Sinch Client SDK in the application to self-sign an authorized request to perform user registration. Choosing this authentication scheme corresponds to initiating the Sinch client by using the factory method that takes both an Application Key and an Application Secret.

    Using this authentication scheme is the quickest way to get started as the client application instances can directly perform authorized requests against the Sinch service.

    Caution: It is not recommended to have the application secret in plain text in the source code in the release version of the application.

    Authentication supported by application server

    This application authentication scheme is based on the client application instance not having direct access to the Application Secret. Instead, when the Sinch client needs to perform an authorized request to register a user identity against the Sinch service, it needs to be provided with an authentication signature and a registration sequence to perform the registration. This should be provided by the application’s backend service, for example, by using a HTTP request over an SSL connection.

    This scheme has the benefit of the application secret never being directly accessible by the client applications and provides a better level of security as well as flexibility.

    Note: The need for the Sinch client to request an authentication signature and registration sequence is only required once per user and device–not on every application launch.

    Figure 4. Authentication Supported by Application Server
    Figure 4. Authentication Supported by Application Server

    Generating the signature

    The Application Server is responsible for generating a valid signature for each registration request that it accepts as a valid user registration. The sequence is a cryptographic nonce, and must be a monotonically increasing value. The signature is then generated as as follows (pseudogrammar):

    string userId;
    string applicationKey; // E.g. "196087a1-e815-4bc4-8984-60d8d8a43f1d"
    string applicationSecret; // E.g. "oYdgGRXoxEuJhGDY2KQ/HQ=="
    uint64 sequence = previous_sequence + 1; // E.g. previous_sequence = 0
    
    string stringToSign = userId + applicationKey + sequence + applicationSecret;
    
    // Use a Base64-encoder that don't introduce line-breaks, 
    // or trim the output signature afterwards.
    string signature = Base64.encode(SHA1.digest(stringToSign));
    

    For example, in Java:

        // Generating the Signature - Java
        // import java.security.MessageDigest;
        // import org.apache.commons.codec.binary.Base64;
    
        String userId; 
        String applicationKey; // E.g. "196087a1-e815-4bc4-8984-60d8d8a43f1d";
        String applicationSecret; // E.g. "oYdgGRXoxEuJhGDY2KQ/HQ==";
        long sequence; // fetch and increment last used sequence
    
        String toSign = userId + applicationKey + sequence + applicationSecret;
    
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
        byte[] hash = messageDigest.digest(toSign.getBytes("UTF-8"));
    
        String signature = Base64.encodeBase64String(hash).trim();
    

    Starting the Client and Providing Authorization Credentials for User Registration

    // Instantiate a client object using the client factory method.
    id<SINClient> client = [Sinch clientWithApplicationKey:@"<application key>" 
                                               environmentHost:@"sandbox.sinch.com" 
                                                        userId:@"<user id>"];
    
    client.delegate = ...;
    
    [client start];
    
    // This will on the first run for this user, call 
    // -[SINClientDelegate client:requiresRegistrationCredentials:], 
    // which implementations could look something like this:
    
    - (void)client:(id<SINClient>)client 
    requiresRegistrationCredentials:(id<SINClientRegistration>) registrationCallback {
    
      // Perform API request to server which keeps the Application Secret
      [myAPIService getAuthorizedSignatureForUser:[client userId]
      onSuccess:^(NSString* signature, long long sequence){
    
        // Forward the signature and sequence back into Sinch SDK
        [registrationCallback registerWithSignature:signature sequence:sequence];
      }
      onFailure:^(NSError* error) {
    
        // Forward potential network request error to Sinch SDK, 
        // e.g. failure due to no internet connection.
        [registrationCallback registerDidFail:error];
      }];
    }
    

    Miscellaneous

    Minimum requirements

    iOS 6.0 is the minimum iOS version required for using the Sinch SDK (iOS Deployment Target).

    Note: The Sinch SDK library uses Automatic Reference Counting (ARC). However, it can still be used in non-ARC projects.

    Note on Sinch.framework file size vs. linked size

    The Sinch.framework file includes a FAT-binary containing the architectures armv7, armv7s, arm64, i386 and x86_64. When linking an application target against the Sinch.framework targeting an iOS device, it will add a approximately 6.1Mb per armv7 slice, and 6.3Mb for the arm64 slice.

    Example: Assuming linking armv7 and arm64 into the final application, it would add approximately 12.4Mb to the application.

    (Even though armv7s is supported and included, we recommend to not build your application for armv7s to reduce the final application binary size)

    Production and Sandbox environments

    Sinch provides two environments:

    • Production - Used for applications deployed in production.
    • Sandbox - Used during development and testing.

    The environment is passed as the parameter environmentHost when instantiating the Sinch client.

    Environment EnvironmentHost parameter
    Production clientapi.sinch.com
    Sandbox sandbox.sinch.com

    Restrictions on User IDs

    User IDs can only contain characters in the printable ASCII character set. That is:

    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~
    

    User IDs must not be longer than 40 characters.

    Encryption export regulations

    Please check the Summary of U.S. Export Controls Applicable to Commercial Encryption Products and ensure that the application is registered for the Encryption Regulations, if applicable. It can be found under this link.

    Statistics

    The Sinch SDK client uploads statistics to the Sinch servers at the end of a call, a call failure, or similar event. The statistics are used for monitoring of network status, call quality, and other aspects regarding the general quality of the service.

    Some of the information is not anonymous and may be associated with the User ID call participants.

    The statistics upload is done by the client in the background.

    Linking against the C++ standard library

    Since Sinch SDK version 3.4.0, it is required to link against libc++. Though if your application is also dependent on libstdc++ (which is now considered deprecated by Apple for use on iOS), you can actually link against both libc++ and libstdc++ by passing the following linker flags:

    • Other Linker Flags -> -ObjC -Xlinker -lc++ -Xlinker -lstdc++

    iOS 7 Compatibility guidelines

    Request user permission for using the microphone

    In iOS 7, additional user privacy constraints are enforced which requires the application to be granted permission to use the device microphone. Unless the application has explicitly requested permission to use the microphone, the user is shown a dialog the first time the microphone is activated.

    In the context of the Sinch SDK, this occurs once the first call is established unless the application has been granted permission earlier. We strongly recommend you explicitly request permission to use the microphone in your application at an appropriate time such as when the user first sets up Sinch. You should not rely on the permission dialog shown when the first Sinch call is established as this will create an awkward user experience.

    By explicitly requesting permission using the methods available in the iOS SDK, the application has more control over when the dialog is shown to the user. This results in a better user experience. Please see the Apple iOS SDK documentation on the class AVAudioSession for details on how request permission to use the microphone.

    iOS 8 App Extensions

    App Extensions is a feature introduced in iOS 8. App extensions are compiled into executables that are separate from the main application executable. The Sinch SDK are using parts of the iOS SDK APIs that are unavailable to app extensions, thus it’s not supported to use the Sinch SDK in an app extension.

    Xcode and Bitcode intermediate representation

    The Sinch SDK supports Bitcode intermediate representation.

    Push Notifications sent via your application server

    In general we strongly recommend using “managed push notifications”, i.e. when push notifications are sent directly from the Sinch cloud, which is described in the section Local and Remote Push Notifications. The following section on the contrary describes integrating support for push notifications but given that your application server maintain the connection with Apple Push Notification Service.

    An application is considered offline in the following scenarios:

    • When the application is not running
    • When background mode has been disabled for the Sinch client, and the application is not in the foreground

    For these scenarios, push notifications can be used to be able to receive incoming calls and instant messages. The following sections cover how to support receiving calls and messages using push notifications.

    When offline, the recipient of a call or message receives a push notification containing a Sinch-specific payload which enables the Sinch client to connect the incoming call or message. Acting on the push notification brings the application to the foreground which allows the user to answer the call or view the message.

    Figure 2. Push notification sequence.
    Figure 2. Push notification sequence.

    Figure 2 describes the following sequence of events: Both users start their applications and Sinch clients. When A (the caller) calls B (the callee), B’s application is in a state where it is not considered online (that is reachable using an active socket connection). Sinch notices that B is not online, and tells A to send a push notification to B so that B can answer the call.

    When the Sinch client on the caller’s (or sender’s) side observes that the destination client is offline, it notifies the application to trigger the sending of a push notification to the callee’s device.

    Push notification data

    On startup, each instance of the application is expected to register a device identifier. The identifier is referred to as push notification data and should be provided to the Sinch client by the method registerPushNotificationData:.

    Push notifications can be addressed to that identifier in the event that the application goes offline.

    The push notification data can be any byte sequence; it is up to you to define its structure and what it contains. However, the push notification data must not exceed 1024 bytes. It should contain enough information to allow your application or application server to use a push service to send a push notification to a specific user of the application on a specific device. For example, an iOS exclusive application would likely use the Apple Push Notification Device Token as push notification data. Multi-platform applications may use a mix of different push services. The following sections assume that Apple Remote Notifications are used, but the use pattern for other push services is similar.

    The push notification data can be unregistered by calling the unregisterPushNotificationData method. This disables incoming calls using push notifications addressed to the specific device.

    Enable push notifications

    Start by enabling support for push notifications when initiating the SINClient:

    #import <Sinch/Sinch.h>
    
    id<SINClient> client = [Sinch clientWithApplicationKey:@"<application key>" 
                                             applicationSecret:@"<application secret>"
                                               environmentHost:@"sandbox.sinch.com" 
                                                        userId:@"<user id>"];
    
    [client setSupportPushNotifications:YES];
    
    client.delegate = ...; 
    
    [client start];
    

    Supporting offline calls and/or messages requires that the application registers for remote push notifications, which in the example that follows is done in the method -[UIApplicationDelegate application:didFinishLaunchingWithOptions:].

    - (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        UIRemoteNotificationType types = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
    }
    

    The next step is to register the push notification data with the SINClient, which in the example below is done by using the APNS device token as push notification data. Upon receiving the the device token from Apple Push Notification Service using the UIApplicationDelegate-method, it is registered with the SINClient.

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        // get previously initiated Sinch client
        id<SINClient> client = [self sinchClient];
    
        [client registerPushNotificationData:deviceToken];
    }
    

    Please refer to Apple’s Local and Push Notification Programming Guide for more information on how to obtain the Apple Push Notification Device Token.

    Sending and receiving Apple push notifications

    To send push messages, you must have a server that is configured for sending push notifications to Apple Push Notification Service. Please see the Sinch REST API User Guide for details on how to handle feedback from Apple Push Notification Service.

    Please also refer to Apple’s Local and Push Notification Programming Guide for further details on push notifications.

    On the caller side

    When the recipient’s application is offline and the app needs to notify the user using a push notification, the caller’s or sender’s application is notified using the delegate method call:shouldSendPushNotifications:.

    Because there might be multiple registered devices for the recipient user (for example, the same user is using the application on both an iPhone and an iPad) the callback is passed an array of SINPushPairs. The pairs contain a payload that is Sinch- and call-specific. Moreover, the pairs contain a push data byte array. The Sinch-specific payload should be embedded in the push notification sent to the recipient’s device(s). The push data is the same push data that the recipient’s application registered earlier.

    - (void)call:(id<SINCall>)call shouldSendPushNotifications:(NSArray *) pushPairs {
        // Send payload and push data to application server
        // which should communicate with Apple Push Notification Service
        // to send push notifications.
    }
    

    NOTE: This example shows the calling case. Messaging works the same way.

    A push notification should be sent to each device, where each pushPair.pushData entry in the array corresponds to one device. The push notification should include the Sinch-specific payload so it can be forwarded to the Sinch client running on the destination device.

    The Sinch-specific payload should be embedded as custom payload data in the Apple Push Notification Payload, see JSON example below.

    {
        "aps" : {
            "alert" : "Incoming call from <user>",
            "sound" : "bingbong.aiff"
        },
        "SIN" : <payload>,
    }
    

    The Sinch-specific payload will not exceed 100 bytes, meaning that there should be 156 bytes available in the push notification payload for application-specific purposes.

    Please refer to Apple’s Local and Push Notification Programming Guide for further details.

    On the callee side

    As a prerequisite, offline calling and messaging must have been enabled on the receiver’s side (see [Push Notifications][]).

    When the application receives a push notification from the Apple Push Notification Service, the application launches and extracts the Sinch-specific payload from the push notification. Once extracted the payload is forwarded to the Sinch client using the method relayRemotePushNotificationPayload:.

    - (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
        NSDictionary* remotePush = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    
        if (remotePush) {
    
            // Extract the Sinch-specific payload from the Apple Remote Push Notification
            NSString* payload = [remotePush objectForKey:@"SIN"]; 
    
            // Get previously initiated Sinch client
            id<SINClient> client = [self sinchClient];
    
            id<SINNotificationResult> result = [client relayRemotePushNotificationPayload:payload];
    
            if (result.isCall && result.callResult.isTimedOut) {
                // Present alert notifying about missed call
            } else if (!result.isValid) {
                // Handle error                
            }
        }
    }
    

    Note: You should have similar logic of relaying the push notification payload to the SINClient-instance in your implementation of -[UIApplicationDelegate application: didReceiveRemoteNotification:].

    Glossary

    This glossary defines some of the domain specific terms used throughout this document.

    Term Explanation
    Application The mobile application running on iOS and/or Android. A partner can have more than one application.
    Application Instance One installation of the application on a single device.
    Application Key A key generated by Sinch. The key is unique to the application. A key looks like 196087a1-e815-4bc4-8984-60d8d8a43f1d (lowercase hexadecimal formatted GUID).
    Application Secret A string generated by Sinch. The secret is used to verify the application. A secret looks like oYdgGRXoxEuJhGDY2KQ/HQ== (Base64-encoded string representation).
    Callee The person receiving a call.
    Caller The person making a call.
    User A user of the mobile application. The actual person holding the mobile device.
    User Identity Identity of a user in the application domain. Can be any string, for instance a user name, user id, phone number or email address.
    Active Connection A socket connection for signaling purposes where incoming calls are received.

    Deprecated features and APIs

    Active Connection in Background

    Apple has since iOS 10 discontinued support for maintaining a VoIP control connection alive via -[UIApplication setKeepAliveTimeout:handler:]. Attempting to use this method on an iOS device running iOS 10 results in the following warning log: Legacy VoIP background mode is deprecated and no longer supported. The Sinch feature Active connection in background was using the keep alive handler API and is as a consequence no longer supported on iOS. It is recommended to use VoIP Push Notifications to achieve the equivalent functionality.

    Third party libraries and copyright notices

    All Third Party Libraries and Copyright notices can be found under this link.