Send mobile push notifications
PubNub connects to Android Firebase Cloud Messaging (FCM) and iOS Apple Push Notification service (APNs) for push notifications.
Create provider keys and add them in the Admin Portal.
FCM also supports iOS. Use one provider or both.
Before you begin, make sure you have:
- Access to the Admin Portal
- Platform credentials (APNs key for iOS, Firebase key for Android)
- A mobile app that requests push notification permissions
A device push token is a unique ID from APNs or FCM that targets a specific app install.
Request a device push token
Register each device with its push provider to get a device push token. Refer to the Android, iOS, and Firebase for iOS documentation for setup.
Register and cache the device push token
After you obtain a device push token, ensure your app always uses the current token. Collect, replace, and cache the device push token. For caching, use UserDefaults
on iOS and SharedPreferences
on Android.
To create the cache:
- Swift
- Objective-C
- Java
- Kotlin
1let tokenDispatch = DispatchQueue(label: "com.pubnub.deviceToken", attributes: .concurrent)
2var cachedToken: Data? {
3 get {
4 var token: Data?
5 tokenDispatch.sync {
6 token = UserDefaults.standard.data(forKey: "com.pubnub.deviceToken")
7 }
8 return token
9 }
10 set {
11 tokenDispatch.async(flags: .barrier) {
12 UserDefaults.standard.set(newValue, forKey: "com.pubnub.deviceToken")
13 }
14 }
15}
1static dispatch_queue_t deviceTokenDispatch;
2static dispatch_queue_t pushChannelsDispatch;
3
4static dispatch_once_t registerCustomDispatchOnceToken;
5- (void) registerCustomDispatchQueues {
6 dispatch_once(®isterCustomDispatchOnceToken, ^{
7 deviceTokenDispatch = dispatch_queue_create("com.pubnub.deviceToken", DISPATCH_QUEUE_CONCURRENT);
8 pushChannelsDispatch = dispatch_queue_create("com.pubnub.pushChannels", DISPATCH_QUEUE_CONCURRENT);
9 });
10}
11
12- (nullable NSData *) cachedToken {
13 __block NSData* token;
14 dispatch_sync(deviceTokenDispatch, ^{
15 token = [[NSUserDefaults standardUserDefaults] dataForKey: @"com.pubnub.deviceToken"];
show all 23 lines1public class SharedPreferencesManager {
2 private static SharedPreferences sharedPref;
3 private SharedPreferencesManager() { }
4
5 public static void init(Context context) {
6 if(sharedPref == null)
7 sharedPref = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
8 }
9
10 public static final String FCM_DEVICE_TOKEN = "PUBNUB_FCM_DEVICE_TOKEN";
11 public static @Nullable String readDeviceToken() {
12 return sharedPref.getString(FCM_DEVICE_TOKEN, null)
13 }
14 public static void writeDeviceToken(String value) {
15 SharedPreferences.Editor prefsEditor = sharedPref.edit();
show all 29 lines1class SharedPreferencesManager private constructor() {
2 companion object {
3 private val sharePref = SharedPreferencesManager()
4 private lateinit var sharedPreferences: SharedPreferences
5
6 private val PLACE_OBJ = "place_obj"
7 private val FCM_DEVICE_TOKEN = "PUBNUB_FCM_DEVICE_TOKEN"
8 private val FCM_CHANNEL_LIST = "PUBNUB_FCM_CHANNEL_LIST"
9
10
11 fun getInstance(context: Context): SharedPreferencesManager {
12 if (!::sharedPreferences.isInitialized) {
13 synchronized(SharedPreferencesManager::class.java) {
14 if (!::sharedPreferences.isInitialized) {
15 sharedPreferences = context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE)
show all 28 linesNext, update the cached device push token when it changes.
- Swift
- Objective-C
- Java
- Kotlin
For more information regarding registering token, go to Apple Docs.
1func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
2 let oldDeviceToken = self.cachedToken
3 guard deviceToken != oldDeviceToken else { return }
4 self.cachedToken = deviceToken
5
6 updateAPNSDevicesOnChannels(
7 pushChannels.allObjects, newDevice: deviceToken, oldDevice: oldDeviceToken,
8 on: "com.mycompany.mybundleid", environment: .production
9 ) { result in
10 switch result {
11 case .success: print("Successfully updated channels with new token")
12 case let .failure(error): print("Failed to update device token due to: \(error)")
13 }
14 }
15}
For more information regarding registering token, go to Apple Docs.
1- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
2 NSData *oldDevice = self.cachedToken;
3 if ([deviceToken isEqualToData:oldDevice]) { return; }
4 self.cachedToken = deviceToken;
5
6 [self updateAPNSDevicesOnChannels:[self.pushChannels allObjects]
7 withDevicePushToken:deviceToken
8 replacingDevicePushToken:oldDevice
9 pushType:PNAPNS2Push
10 environment:PNAPNSProduction
11 topic:@"com.mycompany.mybundleid"
12 andCompletion:^(PNAcknowledgmentStatus * _Nonnull status) {
13 if (!status.isError) {
14 NSLog(@"Successfully updated channels with new token");
15 } else {
show all 19 lines1public class MyFirebaseMessagingService extends FirebaseMessagingService {
2 @Override public void onNewToken(String token) {
3 String oldToken = SharedPreferencesManager.readDeviceToken();
4 if (token.equals(oldToken)) { return; }
5 SharedPreferencesManager.write(token);
6
7 updatePushNotificationsOnChannels(SharedPreferencesManager.readChannelList(), token, oldToken);
8 }
9}
1override fun onNewToken(token: String) {
2 val oldToken = SharedPreferencesManager.getInstance(applicationContext).readDeviceToken()
3 if (token == oldToken) { return }
4 SharedPreferencesManager.getInstance(applicationContext).writeDeviceToken(token)
5
6 updatePushNotificationsOnChannels(
7 SharedPreferencesManager.getInstance(applicationContext).readChannelList(),
8 token,
9 oldToken
10 )
11}
Connect the device to a channel
Initialize your PubNub client with your subscribe and publish keys. Mark specific channels as push channels. In the examples below, ch1
and ch2
are added as push channels.
- Swift
- Objective-C
- Java
- Kotlin
1if let deviceToken = (UIApplication.shared.delegate as? AppDelegate)?.cachedToken {
2 pubnub.addAPNSDevicesOnChannels(
3 ["ch1", "ch2"],
4 device: deviceToken,
5 on: "com.mycompany.mybundleid",
6 environment: .production
7 ) { result in
8 switch result {
9 case let .success(channelsAdded):
10 channelsAdded.forEach { (UIApplication.shared.delegate as? AppDelegate)?.pushChannels.update(with: $0) }
11 case let .failure(error): print("Failed to add Push due to: \(error.localizedDescription)")
12 }
13 }
14}
1NSData *deviceToken = [(AppDelegate *)[[UIApplication sharedApplication] delegate] cachedToken];
2if (deviceToken == nil) { return; }
3
4[self.client addPushNotificationsOnChannels:@[@"ch1",@"ch2"]
5 withDevicePushToken:deviceToken
6 pushType:PNAPNS2Push
7 environment:PNAPNSProduction
8 topic:@"com.mycompany.mybundleid"
9 andCompletion:^(PNAcknowledgmentStatus *status) {
10 if (!status.isError) {
11 NSSet* cachedChannels = [(AppDelegate *)[[UIApplication sharedApplication] delegate] pushChannels];
12 [(AppDelegate *)[[UIApplication sharedApplication] delegate] setPushChannels:[cachedChannels setByAddingObjectsFromArray:@[@"ch1",@"ch2"]]];
13 } else { NSLog(@"Failed to add Push due to: %@", status); }
14}];
1String cachedToken = SharedPreferencesManager.readDeviceToken();
2
3pubnub.addPushNotificationsOnChannels()
4 .pushType(PNPushType.FCM)
5 .deviceId(cachedToken)
6 .channels(Arrays.asList("ch1", "ch2", "ch3"))
7 .async(result -> { /* check result */ });
1SharedPreferencesManager.getInstance(applicationContext).readDeviceToken()?.also { deviceToken ->
2 pubnub.addPushNotificationsOnChannels(
3 pushType = PNPushType.FCM,
4 deviceId = deviceToken,
5 channels = listOf("ch1", "ch2", "ch3")
6 ).async { result, status ->
7 // Handle Response
8 }
9}
Build the push notification message
Specify APNs (pn_apns
) or FCM (pn_fcm
) in the payload. For APNs, set the environment (development
or production
) and the app bundle ID (topic
).
For Apple Push Notification Service:
- JSON
- Swift
- Objective-C
1{
2 "text": "John invited you to chat",
3 "pn_apns": {
4 "aps": {
5 "alert": {
6 "title": "Chat Invitation",
7 "body": "John invited you to chat"
8 }
9 },
10 "pn_push":[
11 {
12 "push_type": "alert",
13 "auth_method": "token",
14 "targets":[
15 {
show all 25 lines1let message = ["text": "John invited you to chat"]
2
3let pushPayload = PubNubPushMessage(
4 apns: PubNubAPNSPayload(
5 aps: APSPayload(alert: .object(.init(title: "Chat Invitation", body: "John invited you to chat"))),
6 pubnub: [.init(targets: [.init(topic: "com.mycompany.mybundleid", environment: .production)])],
7 ),
8 additional: message
9)
1NSDictionary *message = @{
2 @"text": @"John invited you to chat"
3};
4
5PNNotificationsPayload *pushData = [PNNotificationsPayload
6 payloadsWithNotificationTitle:@"Chat Invitation"
7 body:@"John invited you to chat"];
8
9// create the APNs target with topic and environment
10PNAPNSNotificationTarget *target = [PNAPNSNotificationTarget
11 targetForTopic:@"com.mycompany.mybundleid"
12 inEnvironment:PNAPNSProduction
13 withExcludedDevices:nil];
14
15// create the APNs config object and add the target
show all 23 linesFor Firebase:
- Swift
- Objective-C
- JSON(Firebase)
- Java
- Kotlin
1let message = ["text": "John invited you to chat"]
2
3let pushPayload = PubNubPushMessage(
4 fcm: PubNubFCMPayload(
5 payload: nil,
6 target: .topic("invitations"),
7 apns: FCMApnsConfig(
8 headers: [
9 "apns-push-type": "alert", "apns-topic": "com.mycompany.mybundleid", "apns-priority": "10"
10 ],
11 payload: APSPayload(alert: .object(.init(title: "Chat Invitation", body: "John invited you to chat")))
12 )
13 ),
14 additional: message
15)
NSDictionary *message = @{
@"text": @"John invited you to chat"
};
NSDictionary *pushPayload = @{
@"text": @"John invited you to chat",
@"pn_fcm": @{
@"notification": @{
@"title": @"Chat Invitation",
@"body": @"John invited you to chat"
},
@"apns": @{
@"payload": @{
@"aps": @{
@"alert": @{
show all 29 lines1{
2 "text": "John invited you to chat",
3 "pn_fcm": {
4 "android": {
5 "notification": {
6 "title": "Chat Invitation",
7 "body": "John invited you to chat"
8 }
9 },
10 "pn_exceptions" : ["device-token1", "device-token2"]
11 }
12}
1PushPayloadHelper pushPayloadHelper = new PushPayloadHelper();
2PushPayloadHelper.FCMPayload fcmPayload = new PushPayloadHelper.FCMPayload();
3PushPayloadHelper.FCMPayload.Notification fcmNotification =
4 new PushPayloadHelper.FCMPayload.Notification()
5 .setTitle("Chat Invitation")
6 .setBody("John invited you to chat");
7
8fcmPayload.setNotification(fcmNotification);
9pushPayloadHelper.setFcmPayload(fcmPayload);
10
11Map<String, Object> commonPayload = new HashMap<>();
12commonPayload.put("text", "John invited you to chat");
13pushPayloadHelper.setCommonPayload(commonPayload);
14
15Map<String, Object> pushPayload = pushPayloadHelper.build();
1val pushPayloadHelper = PushPayloadHelper()
2
3val fcmPayload = FCMPayload().apply {
4 notification = FCMPayload.Notification().apply {
5 title = "Chat Invitation"
6 body = "John invited you to chat"
7 }
8 custom = mapOf(
9 "topic" to "invitations",
10 "pn_exceptions" to arrayOf("device-token1", "device-token2")
11 )
12}
13pushPayloadHelper.fcmPayload = fcmPayload
14
15pushPayloadHelper.commonPayload = mapOf(
show all 19 linesSend the push notification
Use publish
to send the push. Publish on the same channels you registered for mobile push.
- Java
- Kotlin
- JavaScript
- Swift
- Objective-C
1pubnub.publish()
2 .channel("ch1")
3 .message(pushPayload)
4 .async(result -> { /* check result */ });
1pubnub.publish(
2 channel = "ch1",
3 message = pushPayload
4).async { result ->
5 // Handle Response
6}
1//publish on channel
2pubnub.publish(
3 {
4 channel: "ch1"
5 message: pushPayload
6 },
7 function (status, response) {
8 // Handle Response
9 }
10);
1pubnub.publish(channel: "ch1", message: pushPayload) { result in
2 switch result {
3 case let .success(timetoken):
4 print("Successfully published message at: \(timetoken)")
5 case let .failure(error):
6 print("Failed to publish due to: \(error)")
7 }
8}
1[self.pubnub publish:message toChannel:@"ch1" mobilePushPayload:pushPayload
2 withCompletion:^(PNPublishStatus *status) {
3 if (!status.isError) {
4 NSLog(@"Successfully published message");
5 } else {
6 NSLog(@"Failed to publish due to: %@", status);
7 }
8}];