Push Notifications
Push notifications are sent for different types of events, such as someone following you, commenting on your activity or reacting to it.
Getting them working takes three things: a push provider configured on your dashboard, the provider named in the client's config, and the device's token registered with Stream.
Dashboard configuration
Set up the provider you use (Firebase Cloud Messaging, APNs, Huawei Push Kit or Xiaomi Mi Push) under push providers, and note the name you give the configuration. Registering a device against a provider that is not configured fails.
Which events produce a notification, and what they look like, is configured per feed group. See Feed group push configuration and Push templates.
Client configuration
Name the provider configuration when you build the client:
// Tell the client which push provider configuration your app uses. The name
// is the one you gave the configuration in the Stream dashboard.
final client = StreamFeedsClient(
apiKey: '<your_api_key>',
user: const User(id: 'alice'),
tokenProvider: TokenProvider.static(UserToken('<your_jwt_token>')),
config: const FeedsConfig(
pushNotificationsConfig: PushNotificationsConfig(
pushProviderInfo: PushProviderInfo(
name: 'my-app-firebase',
pushProvider: PushNotificationsProvider.firebase,
),
),
),
);
await client.connect();Registering a device
Getting the device token itself is the platform's job, not this SDK's: firebase_messaging for FCM, or the APNs registration callback on iOS. Once you have it, hand it to createDevice:
// The token comes from the platform: FCM on Android, APNs on iOS. Register
// it after connecting, and again whenever the platform rotates it.
const deviceToken = '<the token your app received from FCM or APNs>';
final result = await client.createDevice(
id: deviceToken,
pushProvider: PushNotificationsProvider.firebase,
pushProviderName: 'my-app-firebase',
);
switch (result) {
case Success():
print('Device registered');
case Failure(error: final error):
print('Failed to register the device: $error');
}Register the token after connecting, and again whenever the platform rotates it.
Removing a device
Remove the device on sign-out, so its user stops receiving notifications there:
// On sign-out, so the user stops receiving notifications on this device
await client.deleteDevice(id: '<the device token>');Listing devices
final result = await client.queryDevices();
for (final device in result.getOrThrow().devices) {
print('${device.id} (${device.pushProvider}/${device.pushProviderName})');
print(' registered ${device.createdAt}');
if (device.disabled ?? false) {
print(' disabled: ${device.disabledReason}');
}
}DeviceResponse carries id, pushProvider, pushProviderName, userId, createdAt, and disabled with a disabledReason when the provider rejected the token.
Sending an activity without a push
skipPush creates the activity without sending a notification for it:
final feed = client.feed(group: 'user', id: 'john');
// The activity is created, but no push notification is sent for it
await feed.addActivity(
request: const FeedAddActivityRequest(
type: 'post',
text: 'A quiet post',
skipPush: true,
),
);Feed.follow takes createNotificationActivity, which is the related but distinct question of whether the follow puts an activity on the target's notification feed. See Notification feeds.
Receiving the notification
Displaying the notification is your app's job. The payload arrives through your push plugin's own handler (FirebaseMessaging.onMessage and onBackgroundMessage for FCM), and what it contains is set by the push template for the feed group.