Skip to content

Commit 1f94077

Browse files
authored
[CIS-1692] Docs for multi-bundle feature (#2110)
* [CIS-1692] Docs + fixes default APN configuration for Demo App.
1 parent a13d411 commit 1f94077

File tree

5 files changed

+73
-20
lines changed

5 files changed

+73
-20
lines changed

DemoApp/Info.plist

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,6 @@
7171
<string>UIInterfaceOrientationLandscapeRight</string>
7272
</array>
7373
<key>PushNotification-Configuration</key>
74-
<string>APN Configuration</string>
74+
<string>APN-Configuration</string>
7575
</dict>
7676
</plist>

Sources/StreamChat/Workers/CurrentUserUpdater.swift

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class CurrentUserUpdater: Worker {
8888
),
8989
completion: { result in
9090
if let error = result.error {
91+
log.debug("Device token \(deviceId) failed to be registered on Stream's backend.\n Reason: \(error.localizedDescription)")
9192
completion?(error)
9293
return
9394
}
Loading
Loading

docusaurus/docs/iOS/guides/push-notifications.md

+71-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Push Notifications
33
---
44

5-
Push notifications can be configured to receive updates when the application is closed or on the background. Stream Chat sends push notification to channel members that are not online and have at least one registered device. Stream supports both **Certificate-based provider connection trust (.p12 certificate)** and **Token-based provider connection trust (JWT)**. Token-based authentication is the preferred way to configure push notifications.
5+
Push notifications can be configured to receive updates when the application is closed or on the background. Stream Chat sends push notification to channel members that are not online and have at least one registered device. Stream supports **Token-based provider connection trust (JWT)**.
66

77
:::note
88
You can find more on setting up push [here](https://getstream.io/chat/docs/ios-swift/push_introduction/?language=swift). Make sure you've taken care of authentication before proceeding to the next steps.
@@ -12,7 +12,7 @@ You can find more on setting up push [here](https://getstream.io/chat/docs/ios-s
1212

1313
To receive push notifications from the Stream server the first step you need to do is register the device. To do this you need to call `UIApplication.shared.registerForRemoteNotifications()` and send the token from `application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)`.
1414

15-
Here is the boilerplate code that you can add to your `AppDelegate`:
15+
Here is the code that you can add to your `AppDelegate`:
1616

1717
```swift
1818
func application(
@@ -32,7 +32,7 @@ func application(
3232
}
3333
```
3434

35-
Because devices are linked to chat users, you should request the device token in the `connectUser` completion block
35+
Because devices are linked to chat users, you should request the device token once the your user is successfully connected to Chat.
3636

3737
```swift
3838
ChatClient.shared.connectUser(
@@ -59,13 +59,65 @@ ChatClient.shared.connectUser(
5959
}
6060
```
6161

62+
### Leveraging Multi-Bundle configuration
63+
64+
If you're interested in leveraging different push configurations per each build type of your app (eg `AppStore`, `Staging`) or similar, you can do so via adding the new `multi-bundle` push configuration in `Push Notifications` tab in your Stream Dashboard.
65+
![Push Notifications](../assets/push_notifications_dashboard.jpg)
66+
67+
You can add new multi-bundle configuration by tapping on `New Configuration` under `Push Notifications` tab and by selecting your preferred push notification provider (eg. `APN`, `Firebase`, ..).
68+
69+
Once created, fill in the following details:
70+
* `Name of your configuration` - this name will be used in `addDevice` registration call.
71+
* `Bundle/Topic ID` - bundle identifier of your app.
72+
* [Team ID](https://help.apple.com/developer-account/#/dev55c3c710c)
73+
* [Key ID](https://help.apple.com/developer-account/#/dev646934554)
74+
* `.p8 token` in raw format.
75+
76+
and `enable` the push configuration by tapping `Enabled` toggle on top right.
77+
Once done, save the new push configuration.
78+
79+
Following example shows how to register your device for given APN push configuration in your app.
80+
81+
```swift
82+
func application(
83+
_ application: UIApplication,
84+
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
85+
) {
86+
guard ChatClient.shared.currentUserId != nil else {
87+
log.warning("cannot add the device without connecting as user first, did you call connectUser")
88+
return
89+
}
90+
91+
/// Specify `providerName:` parameter.
92+
ChatClient.shared.currentUserController().addDevice(.apn(token: deviceToken, providerName: "Name of your configuration")) { error in
93+
if let error = error {
94+
log.warning("adding a device failed with an error \(error)")
95+
}
96+
}
97+
}
98+
```
99+
100+
:::note
101+
`providerName` can be specified only for the push configurations containing the `multi-bundle` badge. If you do not leverage `multi-bundle` setup, leave the `providerName` parameter empty.
102+
103+
![Multi-Bundle Push Configuration](../assets/push_notifications_dashboard_multi_bundle_tag.png)
104+
105+
:::
106+
107+
### Troubleshooting Push Notifications
62108
:::note
63-
Push notifications can be tricky to setup correctly. Make sure to set up [logging](https://getstream.io/chat/docs/ios-swift/push_logs/?language=swift) and check for errors and settings on the [Dashboard](https://getstream.io/dashboard/) and refer to our debugging tips for [common error scenarios](https://getstream.io/chat/docs/ios-swift/push_-_common_issues_and_faq/?language=swift).
109+
Push notifications can be tricky to setup correctly.
64110

111+
Here's few articles that might help to troubleshoot your issues:
112+
* [Sending Push Notifications Using Command-Line Tools (developer.apple.com)](https://developer.apple.com/documentation/usernotifications/sending_push_notifications_using_command-line_tools).
113+
* [Set up logging on Stream Dashboard](https://getstream.io/chat/docs/ios-swift/push_logs/?language=swift)
114+
* [Check for errors and settings on the Dashboard](https://getstream.io/dashboard/) and refer to our debugging tips for [common error scenarios](https://getstream.io/chat/docs/ios-swift/push_-_common_issues_and_faq/?language=swift).
65115
:::
66116

67117
### Removing devices
68118

119+
Usually, you might want to deregister the user's device from push notifications when logging the user out from the Chat.
120+
69121
```swift
70122
guard let deviceId = ChatClient.shared.currentUserController().currentUser?.devices.last?.id else
71123
return
@@ -78,9 +130,9 @@ ChatClient.shared.currentUserController().removeDevice(id: deviceId) { error in
78130
}
79131
```
80132

81-
### Redirecting From Notification To App
133+
### Redirecting From Remote Push Notification To App
82134

83-
In order to redirect the user from notifications to a specific screen in your app, you need to create a `UNUserNotificationCenterDelegate`, your delegate will be called when the app is open from a push notification.
135+
In order to redirect the user from push notification to a specific screen in your app, you need to create a `UNUserNotificationCenterDelegate`. Your delegate will be called when the app is opened from a push notification.
84136

85137
The following code shows how to open the app on the channel after tapping on the push notification:
86138

@@ -110,11 +162,11 @@ class SampleNotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
110162
guard case UNNotificationDefaultActionIdentifier = response.actionIdentifier else {
111163
return
112164
}
113-
165+
114166
/// initialize ChatClient and connect the user
115167
let config = ChatClientConfig(apiKey: .init("<# Api Key Here #>"))
116168
ChatClient.shared = ChatClient(config: config)
117-
169+
118170
let token = Token(stringLiteral: "<# User Token Here #>")
119171
ChatClient.shared = ChatClient(config: config)
120172
ChatClient.shared.connectUser(
@@ -149,7 +201,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
149201
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
150202
guard let scene = scene as? UIWindowScene else { return }
151203
let window = UIWindow(windowScene: scene)
152-
204+
153205
guard let navigationController = UIStoryboard(
154206
name: "Main",
155207
bundle: nil
@@ -165,11 +217,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
165217

166218
}
167219
```
168-
## Customizing Push Notifications
220+
## Customising Remote Push Notifications
169221

170-
Stream sends push notifications ready for iOS to be presented to the user. If you followed this document until now, you app is already receiving clear messages via push notifications.
222+
Stream sends remote push notifications ready for iOS to be presented to the user. If you followed this document until now, your app is already receiving clear messages via push notifications.
171223

172-
In many cases you want the push message to be customized, the best way to do this is via a service extension. A service extension will capture all notifications and allows you to modify its content before presenting it to the user.
224+
In case you need to customise the UI of the received push notification, the best way to do this is via a service extension. A service extension will capture all notifications and allows you to modify its content before presenting it to the user.
173225

174226
### Notification Service Extension
175227

@@ -228,7 +280,7 @@ class NotificationService: UNNotificationServiceExtension {
228280
contentHandler(content)
229281
}
230282
}
231-
283+
232284
override func serviceExtensionTimeWillExpire() {
233285
// Called just before the extension will be terminated by the system.
234286
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
@@ -241,7 +293,7 @@ class NotificationService: UNNotificationServiceExtension {
241293
Let's summarize the most important steps:
242294

243295
- The `ChatClient` is initialized with Api Key and Token, `connectUser` must not be used in a service extension
244-
- `chatHandler.handleNotification` completion block receives a `ChatPushNotificationContent`
296+
- `chatHandler.handleNotification` completion block receives a `ChatPushNotificationContent`
245297
- `ChatPushNotificationContent` is handled for the message case, in that case it will contain a regular `ChatMessage` model
246298

247299
#### Complete Example
@@ -270,13 +322,13 @@ class NotificationService: UNNotificationServiceExtension {
270322
guard let downloadedUrl = downloadedUrl else {
271323
return
272324
}
273-
325+
274326
guard let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else {
275327
return
276328
}
277-
329+
278330
let localURL = URL(fileURLWithPath: path).appendingPathComponent(url.lastPathComponent)
279-
331+
280332
do {
281333
try FileManager.default.moveItem(at: downloadedUrl, to: localURL)
282334
} catch {
@@ -347,14 +399,14 @@ class NotificationService: UNNotificationServiceExtension {
347399
contentHandler(content)
348400
}
349401
}
350-
402+
351403
if !chatNotification {
352404
/// this was not a notification from Stream Chat
353405
/// perform any other transformation to the notification if needed
354406
contentHandler(content)
355407
}
356408
}
357-
409+
358410
override func serviceExtensionTimeWillExpire() {
359411
// Called just before the extension will be terminated by the system.
360412
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.

0 commit comments

Comments
 (0)