Push Notification
This page describes the Push Notifications of ChannelIO iOS SDK (hereafter referred to as SDK).
Set up APNs credentials
Step 1. Create Push Notification Key (Key, Key ID)
If your service already provides push notifications, skip the steps below.
- Issue a key with the Apple Push Notification Service enabled on theย Certificates, Identifiers & Profiles > Keysย page.
- Check the Key ID. Note that you can only download the issued credential key once.
- Check Team ID in. Account > Membership Page.
- Go to Account > Membership tab, and check your Team ID.
Step 2. register APNs Auth Key (.p8) to Channel
- Launch ChannelTalk (PC), go to Settings > Security and Development > Mobile SDK Push Section.
- Upload the downloaded Key file, and fill the Key ID, Bundle ID, and Team ID.
Step 3. register the device token to Channel
Register the device token via initPushToken
to receive remote notifications in Channel.
Referring to the example below, add initPushToken
to the application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
method.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
ChannelIO.initPushToken(deviceToken)
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[ChannelIO initPushTokenWithDeviceToken:deviceToken];
}
Using ChannelIO Notification
Storing Channel.io notification
When aย Channel.ioย remote notification arrives in the background or terminate state, you can save the notification to show when the app is in the foreground state appropriately.
The following is an example of when the user taps the push notification. If it is a Channel.io notification, it notifies you that you have received a push, and saves the notification.
//iOS 10 and above
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
if ChannelIO.isChannelPushNotification(userInfo) {
ChannelIO.receivePushNotification(userInfo)
ChannelIO.storePushNotification(userInfo)
}
completionHandler()
}
//iOS 10 and above
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;
if ([ChannelIO isChannelPushNotification:userInfo]) {
[ChannelIO receivePushNotification:userInfo completion: nil];
[ChannelIO storePushNotification: userInfo];
}
completionHandler();
}
Open ChannelIO chat
If you succeed in saving Channel.io remote notifications through storePushNotification
, you can open a chat containing saved push messages via openStoredPushNotification
method.
Add the following example to the ViewController where you want to open the Channel.io chat.
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if ChannelIO.hasStoredPushNotification() {
ChannelIO.openStoredPushNotification()
}
}
}
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
if ([ChannelIO hasStoredPushNotification]) {
[ChannelIO openStoredPushNotification]
}
}
@end
Combine with follow-up feature
To prevent push notifications and sms from arriving, you need to notify Channel that remote notification arrives.
Go to the Capabilities
tab and add Background Mode
. Turn on both Background fetch
and Remote notification
.
Next, add the receivePushNotification
method to notify the channel that a push notification has arrived successfully. See the example below.
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if ChannelIO.isChannelPushNotification(userInfo) {
// This line
ChannelIO.receivePushNotification(userInfo)
ChannelIO.storePushNotification(userInfo)
}
completionHandler()
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if ([ChannelIO isChannelPushNotification:userInfo]) {
[ChannelIO receivePushNotification:userInfo completion: ^{
completionHandler(UIBackgroundFetchResultNoData);
}];
[ChannelIO storePushNotification: userInfo];
} else {
completionHandler(UIBackgroundFetchResultNoData);
}
}
Notification Extension
This section describes the Notification Extension of SDK. This Extension helps you appropriately respond to theย Channel.io remote push notification, even when the app is background or terminated.
Channel.io recommends adding this Extension. If you do not add this, both follow-up texting and remote notification may arrive.
Extension Setup
- From the Xcode Menu, Click File > New > Targetโฆ .
- In the select a new target window, click Notification Service Extension.
Xcode creates a new Target, and if Swift, you can see two generated files. Three for Objective-C.
The Description of the newly generated file is:
NotificationService.swift
: Write the code used inside the extension target.Info.plist
: info.plist file of extension Target
Setting up Package
1. CocoaPods
Add the SDK dependency to the newly created Extension Target. Modify the Podfile
as follows:
target 'your-notification-extention-target-name' do
...
pod 'ChannelIOSDK', podspec: 'https://mobile-static.channel.io/ios/latest/xcframework.podspec' ...
end
2. Carthage, Swift Package Manager
- Navigate to the project settings for the newly created target.
- Go to the
General
tab. - Add the
ChannelIOFront
package to theFrameworks and Libraries
category.
NotificationService.swift (NotificationService.m)
Add the example below according to your project language settings.
import UserNotifications
import ChannelIOFront
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var content: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
self.content = (request.content.mutableCopy() as? UNMutableNotificationContent)
// this line need to combine sms feature during app terminated
ChannelIO.receivePushNotification(request.content.userInfo)
if let bca = self.content {
func save(_ identifier: String, data: Data, options: [AnyHashable: Any]?) -> UNNotificationAttachment? {
let directory = URL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString, isDirectory: true)
do {
try FileManager.default.createDirectory(
at: directory, withIntermediateDirectories: true, attributes: nil
)
let fileURL = directory.appendingPathComponent(identifier)
try data.write(to: fileURL, options: [])
return try UNNotificationAttachment.init(
identifier: identifier, url: fileURL, options: options
)
} catch {
}
return nil
}
func exitGracefully(_ reason: String = "") {
let bca = request.content.mutableCopy() as? UNMutableNotificationContent
contentHandler(bca!)
}
guard let content = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
return exitGracefully()
}
let userInfo : [AnyHashable: Any] = request.content.userInfo
guard let attachmentURL = (userInfo["thumbUrl"] ?? userInfo["avatarUrl"]) as? String else {
return exitGracefully()
}
guard let imageData = try? Data(contentsOf: URL(string: attachmentURL)!) else {
return exitGracefully()
}
guard let attachment = save("\(attachmentURL.hashValue).png", data: imageData, options: nil) else {
return exitGracefully()
}
content.attachments = [attachment]
contentHandler(content.copy() as! UNNotificationContent)
}
}
override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler, let bac = self.content {
contentHandler(bac)
}
}
}
@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@end
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
if (self.bestAttemptContent != nil) {
UNMutableNotificationContent *content = request.content.mutableCopy;
NSDictionary *userInfo = request.content.userInfo;
NSString *attachmentURL = userInfo[@"avatarUrl"];
if (attachmentURL == nil) {
return [self exitGracefully:request withContentHandler:contentHandler];
}
NSURL *url = [[NSURL alloc] initWithString:attachmentURL];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:url];
if (imageData == nil) {
return [self exitGracefully:request withContentHandler:contentHandler];
}
UNNotificationAttachment *attachment = [self save:[NSString stringWithFormat:@"%ld.png", attachmentURL.hash] data:imageData options:nil];
if (attachmentURL == nil) {
return [self exitGracefully:request withContentHandler:contentHandler];
}
content.attachments = @[attachment];
self.contentHandler(content.copy);
}
}
- (void)exitGracefully:(UNNotificationRequest* )request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
UNMutableNotificationContent *bca = request.content.mutableCopy;
contentHandler(bca);
}
- (UNNotificationAttachment *)save:(NSString *)identifier data:(NSData *)data options:(NSDictionary *)options {
NSURL *directory = [[[NSURL alloc] initFileURLWithPath:NSTemporaryDirectory() isDirectory:YES]
URLByAppendingPathComponent:NSProcessInfo.processInfo.globallyUniqueString];
NSError *error = [[NSError alloc] init];
[[NSFileManager defaultManager] createDirectoryAtURL:directory withIntermediateDirectories:YES attributes:nil error:&error];
if (error != nil) {
return nil;
}
NSURL *fileURL = [directory URLByAppendingPathComponent:identifier];
[data writeToURL:fileURL atomically:YES];
UNNotificationAttachment *ret = [UNNotificationAttachment attachmentWithIdentifier:identifier URL:fileURL options:options error:&error];
if (error != nil) {
return nil;
}
return ret;
}
- (void)serviceExtensionTimeWillExpire {
self.contentHandler(self.bestAttemptContent);
}
@end
Updated 20 days ago