A Voice over Internet Protocol (VoIP) app lets the user make and receive phone calls using an Internet connection instead of the device’s cellular service. Because a VoIP app relies heavily on the network, it’s no surprise that making calls results in high energy use. When not in active use, however, a VoIP app should be completely idle to conserve energy.
In the past, a VoIP app had to maintain a persistent network connection with a server to receive incoming calls and other data. This meant writing complex code that sent periodic messages back and forth between the app and the server to keep a connection alive, even when the app wasn’t in use. This technique resulted in frequent device wakes that wasted energy. It also meant that if a user quit the VoIP app, calls from the server could no longer be received.
Instead of persistent connections, developers should use the PushKit framework—APIs that allows an app to receive pushes (notifications when data is available) from a remote server. Whenever a push is received, the app is called to action. For example, a VoIP app could display an alert when a call is received, and provide an option to accept or reject the call. It could even begin taking precursory steps to initiate the call, in the event the user decides to accept.
There are many advantages to using PushKit to receive VoIP pushes:
The device is woken only when VoIP pushes occur, saving energy.
Unlike standard push notifications, which the user must respond to before your app can perform an action, VoIP pushes go straight to your app for processing.
VoIP pushes are considered high-priority notifications and are delivered without delay.
VoIP pushes can include more data than what is provided with standard push notifications.
Your app is automatically relaunched if it’s not running when a VoIP push is received.
Your app is given runtime to process a push, even if your app is operating in the background.
Like all apps that support background operation, your VoIP app must have background mode enabled in the Xcode Project > Capabilities pane. Select the checkbox for Voice over IP, as shown in Figure 11-1.
You must also create a certificate for your VoIP app. Each VoIP app requires its own individual VoIP Services certificate, mapped to a unique App ID. This certificate allows your notification server to connect to the VoIP service. Visit the Apple Developer Member Center and create a new VoIP Services Certificate. See Figure 11-2. Download the certificate and import it into the Keychain Access app.
To configure your app to receive VoIP push notifications, link to the PushKit framework in your app delegate (or some other location in your app). Then, create a PKPushRegistry
object, set its delegate to self
, and register to receive VoIP pushes. See Listing 11-1.
OBJECTIVE-C
// Link to the PushKit framework
#import <PushKit/PushKit.h>
// Trigger VoIP registration on launch
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self voipRegistration];
return YES;
}
// Register for VoIP notifications
- (void) voipRegistration {
dispatch_queue_t mainQueue = dispatch_get_main_queue()
// Create a push registry object
PKPushRegistry * voipRegistry = [[PKPushRegistry alloc] initWithQueue: mainQueue];
// Set the registry's delegate to self
voipRegistry.delegate = self;
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
}
SWIFT
// Link to the PushKit framework
import PushKit
// Trigger VoIP registration on launch
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
self.voipRegistration()
return true
}
// Register for VoIP notifications
func voipRegistration {
let mainQueue = dispatch_get_main_queue()
// Create a push registry object
let voipRegistry: PKPushRegistry = PKPushRegistry(mainQueue)
// Set the registry's delegate to self
voipRegistry.delegate = self
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [PKPushTypeVoIP]
}
Next, implement a delegate method to handle updated push credentials. If your app receives both standard push notifications and VoIP pushes, then your app will receive two separate push tokens. Both tokens must be passed to the server in order to receive notifications. See Listing 11-2.
OBJECTIVE-C
// Handle updated push credentials
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials: (PKPushCredentials *)credentials forType:(NSString *)type {
// Register VoIP push token (a property of PKPushCredentials) with server
}
SWIFT
// Handle updated push credentials
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// Register VoIP push token (a property of PKPushCredentials) with server
}
Finally, set up a delegate method to process pushes. If your app isn’t running when the push is received, your app will be launched automatically. See Listing 11-3.
OBJECTIVE-C
// Handle incoming pushes
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {
// Process the received push
}
SWIFT
// Handle incoming pushes
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
// Process the received push
}