Push Notifications
Push Notifications provide a way to deliver some information to user while he is not using your app actively. The following use cases can be covered additionally with push notifications:
- send a chat message if recipient is offline (a push notification will be sent automatically)
- make a video call with offline opponents (need to send a push notification manually)
- request to add a user to contact list (need to send a push notification manually)
Create APNS certificate
In order to start working with push notifications functionality you need to do some pre-steps:
- Create APNS certificate. Each iOS application that uses Apple Push Notifications must have an APNS certificate.
- Upload the APNS certificate to ConnectyCube Dashboard panel, Push Notifications module, Settings tab, Apple Push Notification Service (APNS) section.
To get the information on how to create APNS certificates and upload them to Dashboard, please, refer to the How to generate APNS certificate page.
Subscribe
In order to start receiving push notifications you need to get the current device push token and subscribe with it on the backend as follows:
Note: You cannot test push notifications in the iOS simulator. You need a physical iOS device and an Apple developer’s account.
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
...
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *deviceIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
CYBSubscription *subscription = [CYBSubscription subscription];
subscription.notificationChannel = CYBNotificationChannelAPNS;
subscription.deviceUDID = deviceIdentifier;
subscription.deviceToken = deviceToken;
[CYBRequest createSubscription:subscription successBlock:^(NSArray *subscriptions) {
} errorBlock:^(NSError *error) {
}];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Failed to register for notifications:%@", error);
}
@end
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.registerForRemoteNotifications()
return true
}
...
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceIdentifier: String = UIDevice.current.identifierForVendor!.uuidString
let subscription: Subscription! = Subscription()
subscription.notificationChannel = NotificationChannel.APNS
subscription.deviceUDID = deviceIdentifier
subscription.deviceToken = deviceToken
Request.createSubscription(subscription, successBlock: { (subscriptions) in
}) { (error) in
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Failed to register for notifications: \(error.localizedDescription)")
}
}
Note: the device push token can change, even on the same device and with the same user. Make sure to update subscription every time when you get a new device token.
Subscribe for VoIP push notifications
Normally, the VoIP push notifications are used in applications with video/audio calling capabilities.
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 VoIP push notifications.
VoIP push notifications are different than regular APNS notifications mainly in how they are setup in the iOS app. iOS SDK provides the PushKit API to implement VoIP push notifications.
#import <PushKit/PushKit.h>
@interface AppDelegate () <PKPushRegistryDelegate>
@end
@implementation AppDelegate
- (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];
}
// MARK: - PKPushRegistryDelegate protocol
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials: (PKPushCredentials *)credentials forType:(NSString *)type {
// Register VoIP push token (a property of PKPushCredentials) with server
NSString *deviceIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
CYBSubscription *subscription = [CYBSubscription subscription];
subscription.notificationChannel = CYBNotificationChannelAPNSVOIP;
subscription.deviceUDID = deviceIdentifier;
subscription.deviceToken = credentials.token;
[CYBRequest createSubscription:subscription successBlock:^(NSArray *subscriptions) {
} errorBlock:^(NSError *error) {
}];
}
@end
import PushKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> 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]
}
// MARK: - PKPushRegistryDelegate protocol
func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) {
// Register VoIP push token (a property of PKPushCredentials) with server
let deviceIdentifier: String = UIDevice.current.identifierForVendor!.uuidString
let subscription: Subscription! = Subscription()
subscription.notificationChannel = NotificationChannel.APNSVOIP
subscription.deviceUDID = deviceIdentifier
subscription.deviceToken = credentials.token
Request.createSubscription(subscription, successBlock: { (subscriptions) in
}) { (error) in
}
}
}
Send push notifications
You can manually initiate sending of push notifications to user/users on any event in your application. To do so you need to form push notification parameters (payload) and set the push recipients:
CYBEvent *event = [CYBEvent event];
event.notificationType = CYBNotificationTypePush;
event.usersIDs = @"21,22";
event.type = CYBEventTypeOneShot;
NSMutableDictionary *pushParameters = [NSMutableDictionary dictionary];
pushParameters[@"message"] = @"Bitcoin trends";
pushParameters[@"ios_badge"] = @"2";
pushParameters[@"ios_sound"] = @"app_sound.wav";
// custom parameters
pushParameters[@"thread_likes"] = @"24";
pushParameters[@"thread_id"] = @"678923";
NSError *error = nil;
NSData *sendData = [NSJSONSerialization dataWithJSONObject:pushParameters
options:NSJSONWritingPrettyPrinted
error:&error];
NSString *jsonString = [[NSString alloc] initWithData:sendData
encoding:NSUTF8StringEncoding];
event.message = jsonString;
[CYBRequest createEvent:event successBlock:^(NSArray *events) {
} errorBlock:^(NSError *error) {
}];
let event = Event()
event.notificationType = .push
event.usersIDs = "20,21"
event.type = .oneShot
var pushParameters = [String : String]()
pushParameters["message"] = "Bitcoin trends"
pushParameters["ios_badge"] = "2"
pushParameters["ios_sound"] = "app_sound.wav"
// custom params
pushParameters["thread_likes"] = "24"
pushParameters["thread_id"] = "678923"
if let jsonData = try? JSONSerialization.data(withJSONObject: pushParameters,
options: .prettyPrinted) {
let jsonString = String(bytes: jsonData,
encoding: String.Encoding.utf8)
event.message = jsonString
Request.createEvent(event, successBlock: {(events) in
}, errorBlock: {(error) in
})
}
Receive push notifications
// MARK: - AppDelegate
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
}
- (void)application:(UIApplication *)__unused application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
}
// MARK: - AppDelegate
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) {
}
Receive VoIP push notifications
// MARK: - PKPushRegistryDelegate protocol
// Handle incoming pushes
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {
}
// MARK: - PKPushRegistryDelegate protocol
// Handle incoming pushes
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
}
Unsubscribe
The unregister operation allows you to stop receiving push notifications on a selected device:
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
// Unregister from server
NSString *deviceIdentifier = [UIDevice currentDevice].identifierForVendor.UUIDString;
[CYBRequest unregisterSubscriptionForUniqueDeviceIdentifier:deviceIdentifier
successBlock:^() {
} errorBlock:^(NSError *error) {
}];
UIApplication.shared.unregisterForRemoteNotifications()
// Unregister from server
let deviceIdentifier = UIDevice.current.identifierForVendor!.uuidString
Request.unregisterSubscription(forUniqueDeviceIdentifier: deviceIdentifier, successBlock: {
}) { (error) in
}
Unsubscribe VoIP push notifications
// MARK: - PKPushRegistryDelegate protocol
- (void)pushRegistry:(PKPushRegistry *)registry didInvalidatePushTokenForType:(PKPushType)type;
}
// MARK: - PKPushRegistryDelegate protocol
func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) {
}